From 1761de46b07488b4f55f7cceb0f691a15d8efba0 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Tue, 28 Jul 2026 08:53:06 +1200 Subject: [PATCH 01/39] chore(deps): sweep backend and frontend dependencies Combines the open dependabot PRs into one sweep, upgrading as far as each resolver allows rather than stopping at the individually proposed versions. Backend (~90 packages): protobuf 5.29.6 -> 7.35.1, xero-python 14 -> 15, mypy 2.1 -> 2.3, redis 7.4 -> 8.0, matplotlib 3.11.1, litellm 1.93.0, pillow 12.3.0, holidays 0.101 (pin widened to <0.102). Frontend (~410 lock entries): @vueuse/core 13 -> 14, eslint-plugin-vue 10.10.0, vue-router 5.2.0, vue-tsc 3.3.8, vite 8.1.5, eslint 10.8.0, typescript-eslint 8.65.0, axios 1.18.1, dompurify 3.4.12, rrweb-player 2.1.1, plus the fast-uri and shell-quote advisories. Drop google-generativeai: the deprecated legacy Gemini SDK, imported nowhere (the code uses google-genai), and the sole constraint holding protobuf below 6.0. djangorestframework-stubs 3.17 tightens __in lookup and serializer context types, surfacing four real errors: sets that may contain None passed to id__in, a Dict[object, frozenset] passed to job_id__in, and indexed assignment on a now-Mapping serializer context. Fixed at the source rather than baselined; the remaining five new entries are message re-wordings of existing errors, so the synced baseline still shrinks (4396 -> 4388). typescript 7, astroid 4.1.2 and importlib-metadata 9 are left behind: each is pinned out by an upstream package's own latest release (@typescript-eslint <6.1.0, pylint <=4.1.dev0, litellm <9.0). Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Qo7UkADwmj73int333bEnV --- .github/workflows/ci.yml | 6 +- apps/crm/views/phone_call_views.py | 2 +- apps/job/services/kanban_service.py | 4 +- apps/operations/services/scheduler_service.py | 5 +- frontend/package-lock.json | 11797 ++++++++-------- frontend/package.json | 4 +- frontend/src/typed-router.d.ts | 84 +- mypy-baseline.txt | 3266 +++-- poetry.lock | 4545 +++--- pyproject.toml | 3 +- requirements.txt | 197 +- 11 files changed, 9469 insertions(+), 10444 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b29d51ee..cca23aa4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v7 with: python-version: 3.12 cache: 'pip' @@ -87,7 +87,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v7 with: python-version: 3.12 cache: 'pip' @@ -125,7 +125,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v7 with: python-version: 3.12 cache: 'pip' diff --git a/apps/crm/views/phone_call_views.py b/apps/crm/views/phone_call_views.py index 0e8edfe85..4574cd145 100644 --- a/apps/crm/views/phone_call_views.py +++ b/apps/crm/views/phone_call_views.py @@ -267,7 +267,7 @@ def list(self, request: Request, *args: str, **kwargs: str) -> Response: queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) calls = list(page if page is not None else queryset) - context = self.get_serializer_context() + context = dict(self.get_serializer_context()) context["phone_recordings_by_call_id"] = { recording.call_id: recording for recording in PhoneCallRecording.objects.filter( diff --git a/apps/job/services/kanban_service.py b/apps/job/services/kanban_service.py index 1cd1c1d23..05fd4ed8e 100644 --- a/apps/job/services/kanban_service.py +++ b/apps/job/services/kanban_service.py @@ -520,12 +520,12 @@ def build_serialization_context(jobs: List[Job]) -> KanbanSerializationContext: CostSet.objects.filter(id__in=costset_ids).values_list("id", "summary") ) - company_ids = {job.company_id for job in jobs} - {None} + company_ids = {job.company_id for job in jobs if job.company_id is not None} company_names = dict( Company.objects.filter(id__in=company_ids).values_list("id", "name") ) - person_ids = {job.person_id for job in jobs} - {None} + person_ids = {job.person_id for job in jobs if job.person_id is not None} person_names = dict( Person.objects.filter(id__in=person_ids).values_list("id", "name") ) diff --git a/apps/operations/services/scheduler_service.py b/apps/operations/services/scheduler_service.py index 3817cbc42..7573d910b 100644 --- a/apps/operations/services/scheduler_service.py +++ b/apps/operations/services/scheduler_service.py @@ -2,6 +2,7 @@ from dataclasses import dataclass from datetime import date, timedelta from typing import Dict, List, Optional +from uuid import UUID from django.db import models, transaction from django.utils import timezone @@ -110,7 +111,7 @@ def _gather_workshop_staff(today: date) -> List[Staff]: def _classify_jobs( jobs: List[Job], staff_count: int, - assigned_staff_by_job_id: Dict[object, frozenset], + assigned_staff_by_job_id: Dict[UUID, frozenset[UUID]], ) -> tuple[List[JobScheduleState], List[UnschedulableJob]]: """ Separate jobs into schedulable and unschedulable. @@ -397,7 +398,7 @@ def run_workshop_schedule() -> SchedulerRun: ), ) ) - assigned_staff_by_job_id: Dict[object, frozenset] = { + assigned_staff_by_job_id: Dict[UUID, frozenset[UUID]] = { job.id: frozenset() for job in jobs } through_model = Job.people.through diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 33ab94c38..8c0199071 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,7 +21,7 @@ "@types/uuid": "^11.0.0", "@unovis/vue": "^1.5.2", "@vee-validate/zod": "^4.15.1", - "@vueuse/core": "^13.9.0", + "@vueuse/core": "^14.3.0", "@zodios/core": "^10.9.6", "axios": "^1.16.1", "class-variance-authority": "^0.7.1", @@ -74,7 +74,7 @@ "codesight": "^1.18.0", "dotenv": "^17.4.2", "eslint": "^10.7.0", - "eslint-plugin-vue": "~10.8.0", + "eslint-plugin-vue": "~10.10.0", "happy-dom": "^20.8.9", "jiti": "^2.4.2", "lint-staged": "^17.0.3", @@ -102,19 +102,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "14.0.1", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-14.0.1.tgz", + "integrity": "sha512-Oc96zvmxx1fqoSEdUmfmvvb59/KDOnUoJ7s2t7bISyAn0XEz57LCCw8k2Y4Pf3mwKaZLMciESALORLgfe2frCw==", "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.15", @@ -129,6 +120,8 @@ }, "node_modules/@apidevtools/openapi-schemas": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", "license": "MIT", "engines": { "node": ">=10" @@ -136,6 +129,8 @@ }, "node_modules/@apidevtools/swagger-methods": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", "license": "MIT" }, "node_modules/@apidevtools/swagger-parser": { @@ -155,42 +150,6 @@ "openapi-types": ">=7" } }, - "node_modules/@apidevtools/swagger-parser/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@apidevtools/swagger-parser/node_modules/ajv-draft-04": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", - "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", - "license": "MIT", - "peerDependencies": { - "ajv": "^8.5.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/@apidevtools/swagger-parser/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -206,26 +165,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.5", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.27.4", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.4", - "@babel/parser": "^7.27.4", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.4", - "@babel/types": "^7.27.3", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -240,8 +203,16 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -277,11 +248,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -292,6 +265,8 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -353,23 +328,27 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -452,18 +431,22 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.27.6", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.6" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -600,9 +583,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", - "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", "license": "MIT", "peer": true, "engines": { @@ -655,23 +638,23 @@ } }, "node_modules/@docsearch/css": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.2.tgz", - "integrity": "sha512-fH/cn8BjEEdM2nJdjNMHIvOVYupG6AIDtFVDgIZrNzdCSj4KXr9kd+hsehqsNGYjpUjObeKYKvgy/IwCb1jZYQ==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.3.tgz", + "integrity": "sha512-nlOwcXcsNAptQl4vlL4MA78qNJKO0Qlds5GuBjCoePgkebTXLSf8Qt1oyZ3YBshYupKXG9VRGEsk1zr23d+bzQ==", "dev": true, "license": "MIT" }, "node_modules/@docsearch/js": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-4.6.2.tgz", - "integrity": "sha512-qj1yoxl3y4GKoK7+VM6fq/rQqPnvUmg3IKzJ9x0VzN14QVzdB/SG/J6VfV1BWT5RcPUFxIcVwoY1fwHM2fSRRw==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-4.6.3.tgz", + "integrity": "sha512-qUIX2b4Apew3tv4F0qhmgShsl/Lfw4m6mqv/5/5dWNxwTcDdLMp2s3YwZ+NMGh3IKCg0pBaXm7Q5VdyU5Rj+cQ==", "dev": true, "license": "MIT" }, "node_modules/@docsearch/sidepanel-js": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@docsearch/sidepanel-js/-/sidepanel-js-4.6.2.tgz", - "integrity": "sha512-Pni85AP/GwRj7fFg8cBJp0U04tzbueBvWSd3gysgnOsVnQVSZwSYncfErUScLE1CAtR+qocPDFjmYR9AMRNJtQ==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/sidepanel-js/-/sidepanel-js-4.6.3.tgz", + "integrity": "sha512-grGSmvXzG0if+mrzdIKykvpIAuEQ9u0sEJ2eLRRCaQfJvsWqh2C2/aY04bIzWvDh7myi5rvl8D+tUNsVrjYQ3A==", "dev": true, "license": "MIT" }, @@ -726,23 +709,6 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "license": "MIT", - "peer": true - }, - "node_modules/@emotion/babel-plugin/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@emotion/cache": { "version": "11.14.0", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", @@ -828,9 +794,9 @@ "peer": true }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], @@ -844,9 +810,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], @@ -860,9 +826,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -876,9 +842,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -892,9 +858,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -908,9 +874,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -924,9 +890,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -940,9 +906,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -956,9 +922,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -972,9 +938,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -988,9 +954,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -1004,9 +970,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -1020,9 +986,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -1036,9 +1002,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -1052,9 +1018,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -1068,9 +1034,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -1084,9 +1050,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -1100,9 +1066,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -1116,9 +1082,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -1132,9 +1098,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -1148,9 +1114,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -1164,9 +1130,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -1180,9 +1146,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -1196,9 +1162,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -1212,9 +1178,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -1228,9 +1194,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -1244,9 +1210,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", "dev": true, "license": "MIT", "dependencies": { @@ -1287,49 +1253,10 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/config-array/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@eslint/config-helpers": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz", - "integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1377,35 +1304,45 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.7.1", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.9" + "@floating-ui/utils": "^0.2.12" } }, "node_modules/@floating-ui/dom": { - "version": "1.7.1", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.7.1", - "@floating-ui/utils": "^0.2.9" + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" } }, "node_modules/@floating-ui/utils": { - "version": "0.2.9", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", "license": "MIT" }, "node_modules/@floating-ui/vue": { - "version": "1.1.6", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@floating-ui/vue/-/vue-1.1.11.tgz", + "integrity": "sha512-HzHKCNVxnGS35r9fCHBc3+uCnjw9IWIlCPL683cGgM9Kgj2BiAl8x1mS7vtvP6F9S/e/q4O6MApwSHj8hNLGfw==", "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.0.0", - "@floating-ui/utils": "^0.2.9", + "@floating-ui/dom": "^1.7.6", + "@floating-ui/utils": "^0.2.11", "vue-demi": ">=0.13.0" } }, "node_modules/@floating-ui/vue/node_modules/vue-demi": { "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -1429,48 +1366,56 @@ } }, "node_modules/@fontsource-variable/inter": { - "version": "5.2.8", - "resolved": "https://registry.npmjs.org/@fontsource-variable/inter/-/inter-5.2.8.tgz", - "integrity": "sha512-kOfP2D+ykbcX/P3IFnokOhVRNoTozo5/JxhAIVYLpea/UBmCQ/YWPBfWIDuBImXX/15KH+eKh4xpEUyS2sQQGQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@fontsource-variable/inter/-/inter-5.3.0.tgz", + "integrity": "sha512-OupL48va4JNofb97w6NYeF9S7W/kHNKM0Er8Dem5nqi4jeOLrVJDoE8tZEpnMJmtkvNbB1EIPPwHcdkF6b1oUA==", "license": "OFL-1.1", "funding": { "url": "https://github.com/sponsors/ayuhito" } }, "node_modules/@humanfs/core": { - "version": "0.19.1", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.6", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1483,6 +1428,8 @@ }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1494,9 +1441,9 @@ } }, "node_modules/@iconify-json/simple-icons": { - "version": "1.2.79", - "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.79.tgz", - "integrity": "sha512-aNyO7Fd1qej9oQfIyohYFRv0lhQLaZ+6UkK1c1qwax0MDPUOZOdq65MlU500kow97pD/W+b2u1And3e25eE24Q==", + "version": "1.2.92", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.92.tgz", + "integrity": "sha512-hR0ozxR97t1dzWw+esoxFijZ15gagt7EIgF3CNifu2yICXhS7gnun4Y+j+odJQtNSl7wvqMdoLbViIShwe/fdw==", "dev": true, "license": "CC0-1.0", "dependencies": { @@ -1520,7 +1467,9 @@ } }, "node_modules/@internationalized/number": { - "version": "3.6.3", + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.7.tgz", + "integrity": "sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -1528,6 +1477,8 @@ }, "node_modules/@isaacs/cliui": { "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "license": "ISC", "dependencies": { @@ -1542,54 +1493,6 @@ "node": ">=12" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1612,6 +1515,8 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1619,6 +1524,8 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -1633,6 +1540,8 @@ }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", "license": "MIT" }, "node_modules/@juggle/resize-observer": { @@ -1678,9 +1587,9 @@ } }, "node_modules/@kodeglot/vue-calendar/node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -1692,24 +1601,14 @@ }, "node_modules/@liuli-util/fs-extra": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@liuli-util/fs-extra/-/fs-extra-0.1.0.tgz", + "integrity": "sha512-eaAyDyMGT23QuRGbITVY3SOJff3G9ekAAyGqB9joAnTBmqvFN+9a1FazOdO70G6IUqgpKV451eBHYSRcOJ/FNQ==", "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.13", "fs-extra": "^10.1.0" } }, - "node_modules/@liuli-util/fs-extra/node_modules/fs-extra": { - "version": "10.1.0", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@mapbox/geojson-rewind": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz", @@ -1725,12 +1624,13 @@ } }, "node_modules/@mapbox/jsonlint-lines-primitives": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", - "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.3.tgz", + "integrity": "sha512-0SElaV0uMxEnxzBhhX9WTuPyUeMsAN/SS0i16tjuba4/mio63MG9khjC1a0JAiPGXAwvwm4UfHJURCN7nyudQg==", + "license": "MIT", "peer": true, "engines": { - "node": ">= 0.6" + "node": ">= 22" } }, "node_modules/@mapbox/mapbox-gl-supported": { @@ -1748,9 +1648,9 @@ "peer": true }, "node_modules/@mapbox/tiny-sdf": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.1.0.tgz", - "integrity": "sha512-uFJhNh36BR4OCuWIEiWaEix9CA2WzT6CAIcqVjWYpnx8+QDtS+oC4QehRrx5cX4mgWs37MmKnwUejeHxVymzNg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz", + "integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==", "license": "BSD-2-Clause", "peer": true }, @@ -1801,6 +1701,8 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", "dependencies": { @@ -1813,6 +1715,8 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", "engines": { @@ -1821,6 +1725,8 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { @@ -1833,13 +1739,15 @@ }, "node_modules/@one-ini/wasm": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", "dev": true, "license": "MIT" }, "node_modules/@oxc-project/types": { - "version": "0.138.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.138.0.tgz", - "integrity": "sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==", + "version": "0.139.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", + "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" @@ -1847,6 +1755,8 @@ }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", "optional": true, @@ -1855,30 +1765,32 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.7", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": "^14.18.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/pkgr" } }, "node_modules/@playwright/test": { - "version": "1.60.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz", - "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==", + "version": "1.62.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.0.tgz", + "integrity": "sha512-9zOJ6ZQRAena31MpOH9VSzIz8Ou3YJ/wtY/eQm5T2uhfhG7/U3COrMS8xOtUrZrp9OgdmzEnIYODye3nY1VqzA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.60.0" + "playwright": "1.62.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@polka/url": { @@ -1889,17 +1801,14 @@ "license": "MIT" }, "node_modules/@puppeteer/browsers": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.2.tgz", - "integrity": "sha512-JnOSHrAdCQOj27P5QnTrd6bkYd9cXXeFMJS5UJF3UmQbpZQAMMO7AaL0NyrT7i2l/43bwjaHguU+LOpBRyx66w==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.6.tgz", + "integrity": "sha512-B/gKoqlFkzhvzsI6jo9K1cZz9o5ypviVv/xu8CwA4grZzyVwN+XfkT+tu8T1zrauuEXv6VhS2oGX+6NL95WcKA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "debug": "^4.4.3", - "progress": "^2.0.3", - "semver": "^7.7.4", - "tar-fs": "^3.1.1", - "yargs": "^17.7.2" + "modern-tar": "^0.7.6", + "yargs": "^18.0.0" }, "bin": { "browsers": "lib/main-cli.js" @@ -1908,18 +1817,22 @@ "node": ">=22.12.0" }, "peerDependencies": { - "proxy-agent": ">=8.0.1" + "proxy-agent": ">=8.0.1", + "yauzl": "^2.10.0 || ^3.4.0" }, "peerDependenciesMeta": { "proxy-agent": { "optional": true + }, + "yauzl": { + "optional": true } } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.4.tgz", - "integrity": "sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", + "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", "cpu": [ "arm64" ], @@ -1933,9 +1846,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.4.tgz", - "integrity": "sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", "cpu": [ "arm64" ], @@ -1949,9 +1862,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.4.tgz", - "integrity": "sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", + "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", "cpu": [ "x64" ], @@ -1965,9 +1878,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.4.tgz", - "integrity": "sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", + "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", "cpu": [ "x64" ], @@ -1981,9 +1894,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.4.tgz", - "integrity": "sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", + "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", "cpu": [ "arm" ], @@ -1997,9 +1910,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.4.tgz", - "integrity": "sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", + "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", "cpu": [ "arm64" ], @@ -2013,9 +1926,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.4.tgz", - "integrity": "sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", + "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", "cpu": [ "arm64" ], @@ -2029,9 +1942,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.4.tgz", - "integrity": "sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", + "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", "cpu": [ "ppc64" ], @@ -2045,9 +1958,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.4.tgz", - "integrity": "sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", + "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", "cpu": [ "s390x" ], @@ -2061,9 +1974,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.4.tgz", - "integrity": "sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", + "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", "cpu": [ "x64" ], @@ -2077,9 +1990,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.4.tgz", - "integrity": "sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", + "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", "cpu": [ "x64" ], @@ -2093,9 +2006,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.4.tgz", - "integrity": "sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", + "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", "cpu": [ "arm64" ], @@ -2109,9 +2022,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.4.tgz", - "integrity": "sha512-5K83rb36oJiY7BCyE9zLZtGcPV4g5wvq+xwdO0XPIwDVZI8cyB/AUjkNXGb92/rnmezEkjMOpgY61rtwjQtFwg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", + "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", "cpu": [ "wasm32" ], @@ -2127,9 +2040,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.4.tgz", - "integrity": "sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", + "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", "cpu": [ "arm64" ], @@ -2143,9 +2056,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.4.tgz", - "integrity": "sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", + "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", "cpu": [ "x64" ], @@ -2165,9 +2078,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", - "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.3.tgz", + "integrity": "sha512-c0wdcekXtQvvn5Tsrk/+op/gUArrbWaFduBnTLP2l1cKLSQs4diMWjJw3m6A0DdzT8dAAX95KpkJ3qynCePbmw==", "cpu": [ "arm" ], @@ -2179,9 +2092,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", - "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.3.tgz", + "integrity": "sha512-3YjElDdWN+qXAFbJ/CzPV+0wspLqh54k/I6GfdYtEJRqg7buSgc1yPM3B+93j1M4neobtkATHZTmxK2AMVGfnA==", "cpu": [ "arm64" ], @@ -2193,9 +2106,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", - "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.3.tgz", + "integrity": "sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ==", "cpu": [ "arm64" ], @@ -2207,9 +2120,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", - "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.3.tgz", + "integrity": "sha512-LEuncFUHFiF8t4yZVZvvZA1wk0pjAscRnsrn1EfTEmN4HXotBi2YtcnLRyaK6UbuczW7xZS5ES+81Rdz8Z0T6g==", "cpu": [ "x64" ], @@ -2221,9 +2134,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", - "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.3.tgz", + "integrity": "sha512-zvBUvsQUpOWALdDsk6qbS8bXf2VxmPisuudNDrY7x0p0jBdsoZl8HsHczIOgkQiZldmcacMKtBzpoGVNeIe2bQ==", "cpu": [ "arm64" ], @@ -2235,9 +2148,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", - "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.3.tgz", + "integrity": "sha512-C2KmNrcSem/AMg984H/dev+si0lieQGdXdR/lYGJnuumXnFb9Y7QdiI62obFdLlxRYLBv4P0eUVIDbD4c1vVvw==", "cpu": [ "x64" ], @@ -2249,9 +2162,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", - "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.3.tgz", + "integrity": "sha512-ggXnsTAEzNQx74XpunRsiZ9aBZDsI7XIa0hm2nzR9f4WzH5/f/d73ZSDaC5ejJ8YLY4NW+V3wr0tjOaeCq8hqA==", "cpu": [ "arm" ], @@ -2263,9 +2176,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", - "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.3.tgz", + "integrity": "sha512-2vng+FlzNUhKZxtej3IUqJgbZoQk2M/dwQM20+ULV0R/E/8tr9/P6uEf2iiGIk4HL0zMKh5Jry7mUHdUOvyGgA==", "cpu": [ "arm" ], @@ -2277,9 +2190,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", - "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.3.tgz", + "integrity": "sha512-LLLFZKt4/Nraf9rxDkhiU8QVgLF4WmCkfr0L4fj0fPfIZFBib0DeiFk1hhaYKd03LFAFJcxHslhDFlNJLylf5Q==", "cpu": [ "arm64" ], @@ -2291,9 +2204,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", - "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.3.tgz", + "integrity": "sha512-WJkdQCvS9sWNOUBJZfQRKpZGFBztRzcowI+nndmflKgU4XY+3a420FgTOSKTsVqJbnzSxeT4vaJalpOaPo2YCQ==", "cpu": [ "arm64" ], @@ -2305,9 +2218,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", - "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.3.tgz", + "integrity": "sha512-PwHXCCS2n64/1Ot6rP1YEYA02MGYBcQlr8CSZZyrUG2O7NH6NklYmvr9v3Jy+5e/eDeNchc/ukmKJi9LuflMIQ==", "cpu": [ "loong64" ], @@ -2319,9 +2232,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", - "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.3.tgz", + "integrity": "sha512-vUjxINQu3RC8NZS3ykk1gN65gIz8pAopOq2HXuZhiIxHdx7TFvDG+jgrdSgInu1Eza4/Rfi2VzZgyIgEH4WOaw==", "cpu": [ "loong64" ], @@ -2333,9 +2246,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", - "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.3.tgz", + "integrity": "sha512-wzko4aJ13+0G3kGnviCg5gnXFKd40izKsrf2uOw12US4XqprkDrmwOpeW14aSNa37V8bfPcz5Fkob6LZ3BAPmA==", "cpu": [ "ppc64" ], @@ -2347,9 +2260,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", - "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.3.tgz", + "integrity": "sha512-8120ue0JUMSwy11stlwnfdX3pPd+WZYGCDBwEHWtIHi6pOpZmsEF5QKB7a/UN+XFdqvobxz98kv8RTqikyCEBw==", "cpu": [ "ppc64" ], @@ -2361,9 +2274,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", - "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.3.tgz", + "integrity": "sha512-XLFHnR3tXMjbOCh2vtVJHmxt+995uJsTERQyseFDRA0xxMxyTZPLa3OIUlyFaO4mF/Lu0FjmWHCuPXJT1n/IOg==", "cpu": [ "riscv64" ], @@ -2375,9 +2288,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", - "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.3.tgz", + "integrity": "sha512-se6yXvNGMIl0f+RQzyh7XAmia8/9kplQx424wnG2w0C1oi6XgO6Y8otKhdXFHbHs88Ihavzmvh1NWjuovE76BQ==", "cpu": [ "riscv64" ], @@ -2389,9 +2302,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", - "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.3.tgz", + "integrity": "sha512-gNoxRefktVIiGflpONuxWWXZAzIQG++z9qHO3xKwk4WdDMuQja3JHGfE1u0i3PfPDyvhypdk+WrgIJqLhGG7sg==", "cpu": [ "s390x" ], @@ -2403,9 +2316,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", - "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.3.tgz", + "integrity": "sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==", "cpu": [ "x64" ], @@ -2417,9 +2330,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", - "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.3.tgz", + "integrity": "sha512-LBx9LYXvj2CBkMkjLdNAWLwH0MLMin7do2VcVo9kVPibGLkY0BQQut2fv7NVqkXqZ/CrAu9LqDHVV1xHCMpCPw==", "cpu": [ "x64" ], @@ -2431,9 +2344,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", - "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.3.tgz", + "integrity": "sha512-ABVf3Q0RCu7NcyCCOZQI0pJ3GuSdfSl8EXcy88QtdceIMIoCUdfhsJChZ64L9zVM2aJHjde1Bhn5uqSRcX9ySA==", "cpu": [ "x64" ], @@ -2445,9 +2358,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", - "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.3.tgz", + "integrity": "sha512-+2Cy/ldweGBLlPIKsQLF8U5N44a0KDdbrk1rAjHOM9M2K+kGdIVjHLmmrZIcx+9Ny3ke/1JomCsDI1ocb11+sg==", "cpu": [ "arm64" ], @@ -2459,9 +2372,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", - "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.3.tgz", + "integrity": "sha512-dtZvzc8BedpSaFNy75x6uiWwAGTH+aZHDtdrqP6qk+WcLJrfti6sGje1ZJ9UxyzDLF23d/mV+PaMwuC0hL7UVA==", "cpu": [ "arm64" ], @@ -2473,9 +2386,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", - "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.3.tgz", + "integrity": "sha512-Rj8Ra4noo+aYy7sKBggCx0407mws34kAb1ySyWuq5DAtFBQdkSwnsjCgPrhPe9cvgBKZIukpE+CVHvORCS93kQ==", "cpu": [ "ia32" ], @@ -2487,9 +2400,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", - "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.3.tgz", + "integrity": "sha512-vp7N084ew/odXn2gi/mzm9mUkQu9l6AiN6dt4IeUM2Uvm9o+cVmP+YkqbMOteLbiGgqBBlJZjIMYVCfOOIVbVQ==", "cpu": [ "x64" ], @@ -2501,9 +2414,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", - "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.3.tgz", + "integrity": "sha512-MOG/3gTOn4Fwf574RVOaY61I5o6P90legkFADiTyn1hyjNydT+cerU2rLUwPdZkKKyJ+iT+K9p7WXK4LM1Ka6g==", "cpu": [ "x64" ], @@ -2515,46 +2428,46 @@ ] }, "node_modules/@rrweb/packer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@rrweb/packer/-/packer-2.1.0.tgz", - "integrity": "sha512-M3Di2TuUN2xqgwK6OiLgikB0ebU1Wxx6iXMoSiDVhDZRgyc6euL5JQs3GclJOuYstDx+8jjbZ12hTcQe+Ai8WQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@rrweb/packer/-/packer-2.1.1.tgz", + "integrity": "sha512-xPGT7/Cfn1yHD2MOwQhX/8yTvNculurUxPT6ZKXVW8Wh/LI7Jn19L+e8PYKFhj/M89uwNeoTr6hiUQxgb8SMzQ==", "license": "MIT", "dependencies": { - "@rrweb/types": "^2.1.0", + "@rrweb/types": "^2.1.1", "fflate": "^0.4.4" } }, "node_modules/@rrweb/record": { - "version": "2.0.0-alpha.20", - "resolved": "https://registry.npmjs.org/@rrweb/record/-/record-2.0.0-alpha.20.tgz", - "integrity": "sha512-marVOU3Lc285mwLCp+vI6M/eJ+wZ6lcTa7fX0zcdmBsM+j5loXmMQjkmIvkji5+lAbkq5/w2cwto3GS0TaCjtg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@rrweb/record/-/record-2.1.1.tgz", + "integrity": "sha512-c2u175R+daC37PhbjaQV0migxtIXsLuD0mRgRstj/x/CRmLGctRlDi373/4miIUclleq4eZIQXAglH9opclFRQ==", "license": "MIT", "dependencies": { - "@rrweb/types": "^2.0.0-alpha.20", - "@rrweb/utils": "^2.0.0-alpha.20", - "rrweb": "^2.0.0-alpha.20" + "@rrweb/types": "^2.1.1", + "@rrweb/utils": "^2.1.1", + "rrweb": "^2.1.1" } }, "node_modules/@rrweb/replay": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@rrweb/replay/-/replay-2.1.0.tgz", - "integrity": "sha512-a6s3Lzf4iIEL22o6+DHZrbjH/q6OIM9CFh/KzU6pDZ2mOYFP3u3Yd3IL57Oc9usnqFt/kNCvOjUf5JbBrQ9o7A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@rrweb/replay/-/replay-2.1.1.tgz", + "integrity": "sha512-jq64eyJvrh/ioBS1MpDrs/Lj+7QY2TW4xGxp4g4LJKdltSkqMjMbUmhTDcpzaEDZt66S0gasGcgqCulsksSXnw==", "license": "MIT", "dependencies": { - "@rrweb/types": "^2.1.0", - "rrweb": "^2.1.0" + "@rrweb/types": "^2.1.1", + "rrweb": "^2.1.1" } }, "node_modules/@rrweb/types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@rrweb/types/-/types-2.1.0.tgz", - "integrity": "sha512-svOHkcuukP6rIjz2umwVsS7uYct+2h0N97+bg+8IJYKIUj5+YjwIvqx5y9NILFKPIu3yk+Mb+KDFfJ8RV+4JlA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@rrweb/types/-/types-2.1.1.tgz", + "integrity": "sha512-g0I3nCNL1S7slDXwhunxOuOoswkY8WVZJQrPFiwixOc6xoD514d1JLTuyAzCKIox8g/PaLKtV5g31Uk42inQSQ==", "license": "MIT" }, "node_modules/@rrweb/utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@rrweb/utils/-/utils-2.1.0.tgz", - "integrity": "sha512-hU7MT3TSdD+Do7FmMoHrBfPevFCheN5vo2mn97Y4vbXuwemopAmo8dqo5KJeMaA6oQQt7FinHJ0Xqb7k68Ci6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@rrweb/utils/-/utils-2.1.1.tgz", + "integrity": "sha512-x2SgJAD3YJ9eVcLZ5l6OqWMtczdA3VfS5XqPeqpZdQgV9oh6Id5GK2cDN4bimnkqryOcIJdz8cTvV0yNvqQ+nA==", "license": "MIT" }, "node_modules/@shikijs/core": { @@ -2650,7 +2563,9 @@ "license": "MIT" }, "node_modules/@swc/helpers": { - "version": "0.5.17", + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -2669,53 +2584,47 @@ } }, "node_modules/@tailwindcss/node": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", - "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", "license": "MIT", "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "enhanced-resolve": "^5.18.3", - "jiti": "^2.6.1", - "lightningcss": "1.30.2", + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.18" + "tailwindcss": "4.3.3" } }, - "node_modules/@tailwindcss/node/node_modules/tailwindcss": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", - "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", - "license": "MIT" - }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", - "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", "license": "MIT", "engines": { - "node": ">= 10" + "node": ">= 20" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.18", - "@tailwindcss/oxide-darwin-arm64": "4.1.18", - "@tailwindcss/oxide-darwin-x64": "4.1.18", - "@tailwindcss/oxide-freebsd-x64": "4.1.18", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", - "@tailwindcss/oxide-linux-x64-musl": "4.1.18", - "@tailwindcss/oxide-wasm32-wasi": "4.1.18", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", - "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", "cpu": [ "arm64" ], @@ -2725,13 +2634,13 @@ "android" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", - "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", "cpu": [ "arm64" ], @@ -2741,13 +2650,13 @@ "darwin" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", - "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", "cpu": [ "x64" ], @@ -2757,13 +2666,13 @@ "darwin" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", - "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", "cpu": [ "x64" ], @@ -2773,13 +2682,13 @@ "freebsd" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", - "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", "cpu": [ "arm" ], @@ -2789,13 +2698,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", - "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", "cpu": [ "arm64" ], @@ -2805,13 +2714,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", - "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", "cpu": [ "arm64" ], @@ -2821,13 +2730,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", - "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", "cpu": [ "x64" ], @@ -2837,13 +2746,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", - "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", "cpu": [ "x64" ], @@ -2853,13 +2762,13 @@ "linux" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", - "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -2874,75 +2783,21 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.1.0", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.4.0" + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.7.1", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.7.1", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1", - "@tybys/wasm-util": "^0.10.1" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.1", - "inBundle": true, - "license": "0BSD", - "optional": true - }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", - "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", "cpu": [ "arm64" ], @@ -2952,13 +2807,13 @@ "win32" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", - "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", "cpu": [ "x64" ], @@ -2968,667 +2823,162 @@ "win32" ], "engines": { - "node": ">= 10" + "node": ">= 20" } }, "node_modules/@tailwindcss/postcss": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz", - "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz", + "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==", "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.18", - "@tailwindcss/oxide": "4.1.18", - "postcss": "^8.4.41", - "tailwindcss": "4.1.18" + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" } }, - "node_modules/@tailwindcss/postcss/node_modules/tailwindcss": { - "version": "4.1.18", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", - "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", - "license": "MIT" - }, "node_modules/@tailwindcss/typography": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz", - "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==", + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.20.tgz", + "integrity": "sha512-hwbzQuNUfcPvbegQFatVPl/MY/tcM9KLl963hQ5laJKPh81TEZ1+dNG9PirGvcaDBkp+BCshExAyKVPW91dozw==", "license": "MIT", "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" - } - }, - "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" + "tailwindcss": ">=3.0.0 || >=4.0.0 || insiders" } }, "node_modules/@tailwindcss/vite": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.2.tgz", - "integrity": "sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", + "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.3.2", - "@tailwindcss/oxide": "4.3.2", - "tailwindcss": "4.3.2" + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "tailwindcss": "4.3.3" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/node": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.2.tgz", - "integrity": "sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==", - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "5.21.6", - "jiti": "^2.7.0", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.3.2" - } - }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.2.tgz", - "integrity": "sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==", + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", "license": "MIT", "engines": { - "node": ">= 20" + "node": ">=12" }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.2", - "@tailwindcss/oxide-darwin-arm64": "4.3.2", - "@tailwindcss/oxide-darwin-x64": "4.3.2", - "@tailwindcss/oxide-freebsd-x64": "4.3.2", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.2", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.2", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.2", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.2", - "@tailwindcss/oxide-linux-x64-musl": "4.3.2", - "@tailwindcss/oxide-wasm32-wasi": "4.3.2", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.2", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.2" - } - }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.2.tgz", - "integrity": "sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.2.tgz", - "integrity": "sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==", - "cpu": [ - "arm64" - ], + "node_modules/@tanstack/virtual-core": { + "version": "3.17.6", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.17.6.tgz", + "integrity": "sha512-h0/Ebo18CkOrChlQIhNtQkM5ySUnh/GumQ/D1st3hG2HWUPEF+ILUc2k29UtivCi/9G7w7G3/f7Xyd5cCFbKBw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.2.tgz", - "integrity": "sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==", - "cpu": [ - "x64" - ], + "node_modules/@tanstack/vue-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/vue-table/-/vue-table-8.21.3.tgz", + "integrity": "sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, "engines": { - "node": ">= 20" + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "vue": ">=3.2" } }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.2.tgz", - "integrity": "sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==", - "cpu": [ - "x64" - ], + "node_modules/@tanstack/vue-virtual": { + "version": "3.13.34", + "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.13.34.tgz", + "integrity": "sha512-CBqbCcnVsKpl9IJ7frPnbBmAqmc7JttSySg04kgLYJ4yYuC8JsAbtUHP0yLtWGLyByjihN3SwaDCgHQ+Z4iPoA==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" + "dependencies": { + "@tanstack/virtual-core": "3.17.6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.0.0" } }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.2.tgz", - "integrity": "sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } + "node_modules/@tsconfig/node22": { + "version": "22.0.5", + "resolved": "https://registry.npmjs.org/@tsconfig/node22/-/node22-22.0.5.tgz", + "integrity": "sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw==", + "dev": true, + "license": "MIT" }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.2.tgz", - "integrity": "sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } + "node_modules/@tsconfig/svelte": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-1.0.13.tgz", + "integrity": "sha512-5lYJP45Xllo4yE/RUBccBT32eBlRDbqN8r1/MIvQbKxW3aFqaYPCNgm8D5V20X4ShHcwvYWNlKg3liDh1MlBoA==", + "license": "MIT" }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.2.tgz", - "integrity": "sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==", - "cpu": [ - "arm64" - ], + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "license": "MIT", "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.2.tgz", - "integrity": "sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==", - "cpu": [ - "x64" - ], + "node_modules/@types/adm-zip": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.8.tgz", + "integrity": "sha512-RVVH7QvZYbN+ihqZ4kX/dMiowf6o+Jk1fNwiSdx0NahBJLU787zkULhGhJM8mf/obmLGmgdMM0bXsQTmyfbR7Q==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" + "dependencies": { + "@types/node": "*" } }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.2.tgz", - "integrity": "sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==", - "cpu": [ - "x64" - ], + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.2.tgz", - "integrity": "sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], + "node_modules/@types/css-font-loading-module": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz", + "integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==", + "license": "MIT" + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.11.1", - "@emnapi/runtime": "^1.11.1", - "@emnapi/wasi-threads": "^1.2.2", - "@napi-rs/wasm-runtime": "^1.1.4", - "@tybys/wasm-util": "^0.10.2", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.2.tgz", - "integrity": "sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/vite/node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.2.tgz", - "integrity": "sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tailwindcss/vite/node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@tanstack/table-core": { - "version": "8.21.3", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/virtual-core": { - "version": "3.13.10", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/vue-table": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/@tanstack/vue-table/-/vue-table-8.21.3.tgz", - "integrity": "sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw==", - "license": "MIT", - "dependencies": { - "@tanstack/table-core": "8.21.3" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "vue": ">=3.2" - } - }, - "node_modules/@tanstack/vue-virtual": { - "version": "3.13.10", - "license": "MIT", - "dependencies": { - "@tanstack/virtual-core": "3.13.10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "vue": "^2.7.0 || ^3.0.0" - } - }, - "node_modules/@tsconfig/node22": { - "version": "22.0.5", - "resolved": "https://registry.npmjs.org/@tsconfig/node22/-/node22-22.0.5.tgz", - "integrity": "sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/svelte": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-1.0.13.tgz", - "integrity": "sha512-5lYJP45Xllo4yE/RUBccBT32eBlRDbqN8r1/MIvQbKxW3aFqaYPCNgm8D5V20X4ShHcwvYWNlKg3liDh1MlBoA==", - "license": "MIT" - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", - "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/adm-zip": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.7.tgz", - "integrity": "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/css-font-loading-module": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz", - "integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==", - "license": "MIT" - }, - "node_modules/@types/d3": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", - "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", - "license": "MIT", - "peer": true, + "peer": true, "dependencies": { "@types/d3-array": "*", "@types/d3-axis": "*", @@ -3832,16 +3182,16 @@ "peer": true }, "node_modules/@types/d3-random": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", - "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.4.tgz", + "integrity": "sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA==", "license": "MIT", "peer": true }, "node_modules/@types/d3-sankey": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/@types/d3-sankey/-/d3-sankey-0.11.2.tgz", - "integrity": "sha512-U6SrTWUERSlOhnpSrgvMX64WblX1AxX6nEjI2t3mLK2USpQrnbwYYK+AS9SwiE7wgYmOsSSKoSdr8aoKBH0HgQ==", + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/d3-sankey/-/d3-sankey-0.12.5.tgz", + "integrity": "sha512-/3RZSew0cLAtzGQ+C89hq/Rp3H20QJuVRSqFy6RKLe7E0B8kd2iOS1oBsodrgds4PcNVpqWhdUEng/SHvBcJ6Q==", "license": "MIT", "peer": true, "dependencies": { @@ -3983,8 +3333,10 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.8", - "dev": true, + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "devOptional": true, "license": "MIT" }, "node_modules/@types/event-source-polyfill": { @@ -3995,6 +3347,8 @@ }, "node_modules/@types/fs-extra": { "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -4008,9 +3362,9 @@ "peer": true }, "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", "dev": true, "license": "MIT", "dependencies": { @@ -4032,6 +3386,8 @@ }, "node_modules/@types/json-schema": { "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, "node_modules/@types/leaflet": { @@ -4046,6 +3402,8 @@ }, "node_modules/@types/linkify-it": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", "dev": true, "license": "MIT" }, @@ -4070,6 +3428,8 @@ }, "node_modules/@types/markdown-it": { "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "dev": true, "license": "MIT", "dependencies": { @@ -4089,17 +3449,21 @@ }, "node_modules/@types/mdurl": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true, "license": "MIT" }, "node_modules/@types/ms": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "license": "MIT" }, "node_modules/@types/node": { - "version": "25.9.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz", - "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==", + "version": "25.9.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.5.tgz", + "integrity": "sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==", "license": "MIT", "dependencies": { "undici-types": ">=7.24.0 <7.24.7" @@ -4160,371 +3524,149 @@ "peer": true }, "node_modules/@types/topojson": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@types/topojson/-/topojson-3.2.6.tgz", - "integrity": "sha512-ppfdlxjxofWJ66XdLgIlER/85RvpGyfOf8jrWf+3kVIjEatFxEZYD/Ea83jO672Xu1HRzd/ghwlbcZIUNHTskw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/geojson": "*", - "@types/topojson-client": "*", - "@types/topojson-server": "*", - "@types/topojson-simplify": "*", - "@types/topojson-specification": "*" - } - }, - "node_modules/@types/topojson-client": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/topojson-client/-/topojson-client-3.1.5.tgz", - "integrity": "sha512-C79rySTyPxnQNNguTZNI1Ct4D7IXgvyAs3p9HPecnl6mNrJ5+UhvGNYcZfpROYV2lMHI48kJPxwR+F9C6c7nmw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/geojson": "*", - "@types/topojson-specification": "*" - } - }, - "node_modules/@types/topojson-server": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/topojson-server/-/topojson-server-3.0.4.tgz", - "integrity": "sha512-5+ieK8ePfP+K2VH6Vgs1VCt+fO1U8XZHj0UsF+NktaF0DavAo1q3IvCBXgokk/xmtvoPltSUs6vxuR/zMdOE1g==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/geojson": "*", - "@types/topojson-specification": "*" - } - }, - "node_modules/@types/topojson-simplify": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/topojson-simplify/-/topojson-simplify-3.0.3.tgz", - "integrity": "sha512-sBO5UZ0O2dB0bNwo0vut2yLHhj3neUGi9uL7/ROdm8Gs6dtt4jcB9OGDKr+M2isZwQM2RuzVmifnMZpxj4IGNw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/geojson": "*", - "@types/topojson-specification": "*" - } - }, - "node_modules/@types/topojson-specification": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.5.tgz", - "integrity": "sha512-C7KvcQh+C2nr6Y2Ub4YfgvWvWCgP2nOQMtfhlnwsRL4pYmmwzBS7HclGiS87eQfDOU/DLQpX6GEscviaz4yLIQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "license": "MIT", - "optional": true - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/uuid": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-11.0.0.tgz", - "integrity": "sha512-HVyk8nj2m+jcFRNazzqyVKiZezyhDKrGUA3jlEcg/nZ6Ms+qHwocba1Y/AaVaznJTAM9xpdFSh+ptbNrhOGvZA==", - "deprecated": "This is a stub types definition. uuid provides its own type definitions, so you do not need this installed.", - "license": "MIT", - "dependencies": { - "uuid": "*" - } - }, - "node_modules/@types/web-bluetooth": { - "version": "0.0.21", - "license": "MIT" - }, - "node_modules/@types/whatwg-mimetype": { - "version": "3.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.4.tgz", - "integrity": "sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/type-utils": "8.59.4", - "@typescript-eslint/utils": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.59.4", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/project-service": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.4.tgz", - "integrity": "sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.4", - "@typescript-eslint/types": "^8.59.4", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.4.tgz", - "integrity": "sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.4.tgz", - "integrity": "sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.4.tgz", - "integrity": "sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4", - "@typescript-eslint/utils": "8.59.4", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@types/topojson/-/topojson-3.2.6.tgz", + "integrity": "sha512-ppfdlxjxofWJ66XdLgIlER/85RvpGyfOf8jrWf+3kVIjEatFxEZYD/Ea83jO672Xu1HRzd/ghwlbcZIUNHTskw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/geojson": "*", + "@types/topojson-client": "*", + "@types/topojson-server": "*", + "@types/topojson-simplify": "*", + "@types/topojson-specification": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.4.tgz", - "integrity": "sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==", - "dev": true, + "node_modules/@types/topojson-client": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/topojson-client/-/topojson-client-3.1.5.tgz", + "integrity": "sha512-C79rySTyPxnQNNguTZNI1Ct4D7IXgvyAs3p9HPecnl6mNrJ5+UhvGNYcZfpROYV2lMHI48kJPxwR+F9C6c7nmw==", "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peer": true, + "dependencies": { + "@types/geojson": "*", + "@types/topojson-specification": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.4.tgz", - "integrity": "sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==", - "dev": true, + "node_modules/@types/topojson-server": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/topojson-server/-/topojson-server-3.0.4.tgz", + "integrity": "sha512-5+ieK8ePfP+K2VH6Vgs1VCt+fO1U8XZHj0UsF+NktaF0DavAo1q3IvCBXgokk/xmtvoPltSUs6vxuR/zMdOE1g==", "license": "MIT", + "peer": true, "dependencies": { - "@typescript-eslint/project-service": "8.59.4", - "@typescript-eslint/tsconfig-utils": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "@types/geojson": "*", + "@types/topojson-specification": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.4.tgz", - "integrity": "sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==", - "dev": true, + "node_modules/@types/topojson-simplify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/topojson-simplify/-/topojson-simplify-3.0.3.tgz", + "integrity": "sha512-sBO5UZ0O2dB0bNwo0vut2yLHhj3neUGi9uL7/ROdm8Gs6dtt4jcB9OGDKr+M2isZwQM2RuzVmifnMZpxj4IGNw==", "license": "MIT", + "peer": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/typescript-estree": "8.59.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "@types/geojson": "*", + "@types/topojson-specification": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.4.tgz", - "integrity": "sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==", - "dev": true, + "node_modules/@types/topojson-specification": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.5.tgz", + "integrity": "sha512-C7KvcQh+C2nr6Y2Ub4YfgvWvWCgP2nOQMtfhlnwsRL4pYmmwzBS7HclGiS87eQfDOU/DLQpX6GEscviaz4yLIQ==", "license": "MIT", + "peer": true, "dependencies": { - "@typescript-eslint/types": "8.59.4", - "eslint-visitor-keys": "^5.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@types/geojson": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } + "optional": true }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-11.0.0.tgz", + "integrity": "sha512-HVyk8nj2m+jcFRNazzqyVKiZezyhDKrGUA3jlEcg/nZ6Ms+qHwocba1Y/AaVaznJTAM9xpdFSh+ptbNrhOGvZA==", + "deprecated": "This is a stub types definition. uuid provides its own type definitions, so you do not need this installed.", "license": "MIT", "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" + "uuid": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-mimetype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", + "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } + "license": "MIT" }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 4" + "dependencies": { + "@types/node": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.65.0.tgz", + "integrity": "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "brace-expansion": "^5.0.5" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/type-utils": "8.65.0", + "@typescript-eslint/utils": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "18 || 20 || >=22" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.65.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.64.0.tgz", - "integrity": "sha512-KA0OshtlcCCXmbfqyZkM5pV3/WNraJf7DkJRLpyrmwPtud57H5BDX7C3k0LPSPxpprfRL+cJDGabF10mvNCoCw==", + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.65.0.tgz", + "integrity": "sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.64.0", - "@typescript-eslint/types": "8.64.0", - "@typescript-eslint/typescript-estree": "8.64.0", - "@typescript-eslint/visitor-keys": "8.64.0", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0", "debug": "^4.4.3" }, "engines": { @@ -4539,15 +3681,15 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/project-service": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.64.0.tgz", - "integrity": "sha512-tk4WpOJ6IEbGrVHaNmM0YRrwAD3exZlIK3iadQNAxh4YKk6jvUQ4ecq18n+v7+meh+cJ3j+D8nbk8sRKhlwLQg==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz", + "integrity": "sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.64.0", - "@typescript-eslint/types": "^8.64.0", + "@typescript-eslint/tsconfig-utils": "^8.65.0", + "@typescript-eslint/types": "^8.65.0", "debug": "^4.4.3" }, "engines": { @@ -4561,15 +3703,15 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.64.0.tgz", - "integrity": "sha512-CXEaFdYXjSTgKhisNkwCcJwTP8Pl+fmRrEQrri4nm3vU743bALrxzLmq7fHG/7e6a5xO0lDYeURpZmBuhHk54w==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.65.0.tgz", + "integrity": "sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.64.0", - "@typescript-eslint/visitor-keys": "8.64.0" + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4579,10 +3721,10 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.64.0.tgz", - "integrity": "sha512-2yo8rRNKuzbVWQp5kslhANqZ2uDAeROQHBRZNPu8JDsHmeFNj/XJJhX/FhNUWmkHHvoNsKa6+tHJiig87EzsQw==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.65.0.tgz", + "integrity": "sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==", "dev": true, "license": "MIT", "engines": { @@ -4596,35 +3738,17 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.64.0.tgz", - "integrity": "sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.64.0.tgz", - "integrity": "sha512-Pztpsn1aCE1oWDvDEfUk31nngvvF7vUB5SwHFEaZIFpvw7WJtqUHHL4plBZDA9HfWJJjL13BdG0YrJInTUvoVA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.65.0.tgz", + "integrity": "sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.64.0", - "@typescript-eslint/tsconfig-utils": "8.64.0", - "@typescript-eslint/types": "8.64.0", - "@typescript-eslint/visitor-keys": "8.64.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/utils": "8.65.0", "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "engines": { @@ -4635,19 +3759,16 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.64.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.64.0.tgz", - "integrity": "sha512-mrtuL8Nsn6gi2H4mo5KMTp823M+3Q19Ew/i+Zlikq20tIMm99C3Ez0dCmkWWnxut20esQvTg8aUSEhMcAOXhEw==", + "node_modules/@typescript-eslint/types": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz", + "integrity": "sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==", "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.64.0", - "eslint-visitor-keys": "^5.0.0" - }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -4656,67 +3777,22 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", - "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/scope-manager": { + "node_modules/@typescript-eslint/typescript-estree": { "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.65.0.tgz", - "integrity": "sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.65.0.tgz", + "integrity": "sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==", "dev": true, "license": "MIT", "dependencies": { + "@typescript-eslint/project-service": "8.65.0", + "@typescript-eslint/tsconfig-utils": "8.65.0", "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0" + "@typescript-eslint/visitor-keys": "8.65.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4724,20 +3800,33 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/types": { + "node_modules/@typescript-eslint/utils": { "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz", - "integrity": "sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.65.0.tgz", + "integrity": "sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==", "dev": true, "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { @@ -4772,9 +3861,9 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", "dev": true, "license": "ISC" }, @@ -4800,17 +3889,35 @@ } }, "node_modules/@unovis/ts": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@unovis/ts/-/ts-1.6.2.tgz", - "integrity": "sha512-kSOWRiZsU4Kk1yuJSSaJs+zJCKNg3+2A0/6/7/y1Cu5uHggwGPeE3CzKaNOal/Hpc46bnZw2VLI23mY+gDFbeQ==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@unovis/ts/-/ts-1.6.7.tgz", + "integrity": "sha512-CXmr+EQQyba9vqcyhvc963y06agBvaX0ut+lylTSUo4A/t1YYdrFQFKUULasdVY6Pe+OK5xveZOlJrYDiPOX3A==", "license": "Apache-2.0", "peer": true, "dependencies": { "@emotion/css": "^11.7.1", "@juggle/resize-observer": "^3.3.1", "@types/d3": "^7.4.0", + "@types/d3-array": "~3.2.2", + "@types/d3-axis": "~3.0.6", + "@types/d3-brush": "~3.0.6", + "@types/d3-chord": "~3.0.6", "@types/d3-collection": "^1.0.10", - "@types/d3-sankey": "^0.11.2", + "@types/d3-color": "~3.1.3", + "@types/d3-drag": "~3.0.7", + "@types/d3-ease": "~3.0.2", + "@types/d3-force": "~3.0.10", + "@types/d3-geo": "~3.1.0", + "@types/d3-hierarchy": "~3.1.7", + "@types/d3-interpolate": "~3.0.4", + "@types/d3-path": "~3.1.1", + "@types/d3-sankey": "^0.12.4", + "@types/d3-scale": "~4.0.9", + "@types/d3-selection": "~3.0.0", + "@types/d3-shape": "~3.1.7", + "@types/d3-timer": "~3.0.2", + "@types/d3-transition": "~3.0.9", + "@types/d3-zoom": "~3.0.8", "@types/dagre": "^0.7.50", "@types/geojson": "^7946.0.8", "@types/leaflet": "1.7.6", @@ -4823,859 +3930,570 @@ "@unovis/dagre-layout": "0.8.8-2", "@unovis/graphlibrary": "2.2.0-2", "d3": "^7.2.1", + "d3-array": "~3", + "d3-axis": "~3", + "d3-brush": "~3", + "d3-chord": "~3", "d3-collection": "^1.0.7", + "d3-color": "~3", + "d3-drag": "~3", + "d3-ease": "~3", + "d3-force": "~3", + "d3-geo": "~3", "d3-geo-projection": "^4.0.0", + "d3-hierarchy": "~3", + "d3-interpolate": "~3", "d3-interpolate-path": "^2.2.3", + "d3-path": "~3", "d3-sankey": "^0.12.3", + "d3-scale": "~4", + "d3-selection": "~3", + "d3-shape": "~3", + "d3-timer": "~3", + "d3-transition": "~3", + "d3-zoom": "~3", "elkjs": "^0.10.0", "geojson": "^0.5.0", "leaflet": "1.7.1", "maplibre-gl": "^2.1.9", "striptags": "^3.2.0", "supercluster": "^7.1.5", - "three": "^0.135.0", - "throttle-debounce": "^5.0.0", - "to-px": "^1.1.0", - "topojson-client": "^3.1.0", - "tslib": "^2.3.1" - } - }, - "node_modules/@unovis/vue": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@unovis/vue/-/vue-1.6.2.tgz", - "integrity": "sha512-vFglLeiTnNk8VaCEjctAMQXi8Vi+dc217JLkbiIkOLNLXzOClv1ZLv7QjKplRHG+eq/DKC17WSBKINsjXuYbtQ==", - "license": "Apache-2.0", - "peerDependencies": { - "@unovis/ts": "1.6.2", - "vue": "^3" - } - }, - "node_modules/@vee-validate/zod": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/@vee-validate/zod/-/zod-4.15.1.tgz", - "integrity": "sha512-329Z4TDBE5Vx0FdbA8S4eR9iGCFFUNGbxjpQ20ff5b5wGueScjocUIx9JHPa79LTG06RnlUR4XogQsjN4tecKA==", - "license": "MIT", - "dependencies": { - "type-fest": "^4.8.3", - "vee-validate": "4.15.1" - }, - "peerDependencies": { - "zod": "^3.24.0" - } - }, - "node_modules/@vitejs/plugin-vue": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.8.tgz", - "integrity": "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rolldown/pluginutils": "^1.0.1" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@vitest/expect": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.7.tgz", - "integrity": "sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.1.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.7", - "@vitest/utils": "4.1.7", - "chai": "^6.2.2", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.7.tgz", - "integrity": "sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "4.1.7", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/mocker/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.7.tgz", - "integrity": "sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.7.tgz", - "integrity": "sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.1.7", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.7.tgz", - "integrity": "sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.7", - "@vitest/utils": "4.1.7", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.7.tgz", - "integrity": "sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.7.tgz", - "integrity": "sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.7", - "convert-source-map": "^2.0.0", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@volar/language-core": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", - "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/source-map": "2.4.28" - } - }, - "node_modules/@volar/source-map": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", - "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@volar/typescript": { - "version": "2.4.28", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", - "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/language-core": "2.4.28", - "path-browserify": "^1.0.1", - "vscode-uri": "^3.0.8" - } - }, - "node_modules/@vue-macros/common": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vue-macros/common/-/common-3.1.2.tgz", - "integrity": "sha512-h9t4ArDdniO9ekYHAD95t9AZcAbb19lEGK+26iAjUODOIJKmObDNBSe4+6ELQAA3vtYiFPPBtHh7+cQCKi3Dng==", - "license": "MIT", - "dependencies": { - "@vue/compiler-sfc": "^3.5.22", - "ast-kit": "^2.1.2", - "local-pkg": "^1.1.2", - "magic-string-ast": "^1.0.2", - "unplugin-utils": "^0.3.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/sponsors/vue-macros" - }, - "peerDependencies": { - "vue": "^2.7.0 || ^3.2.25" - }, - "peerDependenciesMeta": { - "vue": { - "optional": true - } - } - }, - "node_modules/@vue/babel-helper-vue-transform-on": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", - "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vue/babel-plugin-jsx": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", - "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.2", - "@vue/babel-helper-vue-transform-on": "1.5.0", - "@vue/babel-plugin-resolve-type": "1.5.0", - "@vue/shared": "^3.5.18" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - } + "three": "^0.135.0", + "throttle-debounce": "^5.0.0", + "topojson-client": "^3.1.0", + "tslib": "^2.3.1" } }, - "node_modules/@vue/babel-plugin-resolve-type": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", - "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/parser": "^7.28.0", - "@vue/compiler-sfc": "^3.5.18" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" - }, + "node_modules/@unovis/vue": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@unovis/vue/-/vue-1.6.7.tgz", + "integrity": "sha512-iyYdwwI8Tm8Kyb3aUvG3GVmId6gcmw8EY2Qbaim1W4uqktDYViFzJXIjLPbNir4ju+ziXmaxM2sfhfEC3t3TYw==", + "license": "Apache-2.0", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@unovis/ts": "1.6.7", + "vue": "^3" } }, - "node_modules/@vue/compiler-core": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.39.tgz", - "integrity": "sha512-16KBTEXAJCpDr0mwlw+AZyhu8iyC7R3S2vBwsI7QnWJU6X3WKc9VKeNEZpiMdZ569qWhz9574L3vV55qRL0Vtw==", + "node_modules/@vee-validate/zod": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@vee-validate/zod/-/zod-4.15.1.tgz", + "integrity": "sha512-329Z4TDBE5Vx0FdbA8S4eR9iGCFFUNGbxjpQ20ff5b5wGueScjocUIx9JHPa79LTG06RnlUR4XogQsjN4tecKA==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.7", - "@vue/shared": "3.5.39", - "entities": "^7.0.1", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" + "type-fest": "^4.8.3", + "vee-validate": "4.15.1" + }, + "peerDependencies": { + "zod": "^3.24.0" } }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.39.tgz", - "integrity": "sha512-oQPigALqYbNxTNPvNgSOe+czwVExfbVF02lz8jP0S3AXJiu3jxYDygNUiqSep4ezzW8XgnubqH63My2A7JR/vg==", + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.8.tgz", + "integrity": "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==", + "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.39", - "@vue/shared": "3.5.39" + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" } }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.39.tgz", - "integrity": "sha512-d0ki86iOyN8LoZPBmk5SJWNwHP19CnDDCfuo//+2WJa2g5Ke0Jay983PIBIcSSzldC68I8DrD5GrHV3OSDfodg==", + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.7", - "@vue/compiler-core": "3.5.39", - "@vue/compiler-dom": "3.5.39", - "@vue/compiler-ssr": "3.5.39", - "@vue/shared": "3.5.39", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.21", - "postcss": "^8.5.15", - "source-map-js": "^1.2.1" + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.39.tgz", - "integrity": "sha512-Ce7/wvwMHai74bdszfXExdazFigYnlF9zgCmEQUcM1j0fOymlouZ7XilTYNo8oUjhlnjYOZbGrcYKuqjz89Ucw==", + "node_modules/@vitest/mocker": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.39", - "@vue/shared": "3.5.39" + "@vitest/spy": "4.1.10", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/@vue/devtools-api": { - "version": "7.7.7", + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-kit": "^7.7.7" + "@types/estree": "^1.0.0" } }, - "node_modules/@vue/devtools-core": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.1.5.tgz", - "integrity": "sha512-5e5jQOEssCdZA1wlFEUkIDtb+cAOWuLNWJ52fm4PBWbF7e3oTnM2fneaL42E5lJoolAaUQ678tv/XEb3h4e86Q==", + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-kit": "^8.1.5", - "@vue/devtools-shared": "^8.1.5" + "tinyrainbow": "^3.1.0" }, - "peerDependencies": { - "vue": "^3.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vue/devtools-core/node_modules/@vue/devtools-kit": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.1.5.tgz", - "integrity": "sha512-FcSAxsi4eWuXLCB7Rv9lj0aIVHHPNVQ2BazGf4RJTc2JCqb4BQg0hk87ZFhminCfl+mD5OUI0rX2cgyu4kJOGA==", + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-shared": "^8.1.5", - "birpc": "^2.6.1", - "hookable": "^5.5.3", - "perfect-debounce": "^2.0.0" + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vue/devtools-core/node_modules/@vue/devtools-shared": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.1.5.tgz", - "integrity": "sha512-mhT4zcPFhF+Xk1O4BfhhrbXzpmfqY03fS6xGpcllbQG7lDjhQf8pQHcTIhqQIYx1hfwtHmk/6jM96ele0UxPqQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vue/devtools-core/node_modules/perfect-debounce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", - "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", "dev": true, - "license": "MIT" - }, - "node_modules/@vue/devtools-kit": { - "version": "7.7.9", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", - "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", "license": "MIT", "dependencies": { - "@vue/devtools-shared": "^7.7.9", - "birpc": "^2.3.0", - "hookable": "^5.5.3", - "mitt": "^3.0.1", - "perfect-debounce": "^1.0.0", - "speakingurl": "^14.0.1", - "superjson": "^2.2.2" + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vue/devtools-shared": { - "version": "7.7.9", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", - "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "dev": true, "license": "MIT", - "dependencies": { - "rfdc": "^1.4.1" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vue/eslint-config-prettier": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-10.2.0.tgz", - "integrity": "sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==", + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", "dev": true, "license": "MIT", "dependencies": { - "eslint-config-prettier": "^10.0.1", - "eslint-plugin-prettier": "^5.2.2" + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" }, - "peerDependencies": { - "eslint": ">= 8.21.0", - "prettier": ">= 3.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vue/eslint-config-typescript": { - "version": "14.9.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.9.0.tgz", - "integrity": "sha512-E3j9hDlfVf10F30MRcLTPY2IIhWIx1nsvkVukk14kTcuA+oBVot9zsP1hzsO+PAMDxV3Fd9FimBJtUBNBL5KFA==", + "node_modules/@vitest/utils/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/utils": "^8.60.0", - "fast-glob": "^3.3.3", - "typescript-eslint": "^8.60.0", - "vue-eslint-parser": "^10.4.0" - }, - "bin": { - "vue-eslint-config-typescript": "dist/bin.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": "^9.10.0 || ^10.0.0", - "eslint-plugin-vue": "^9.28.0 || ^10.0.0", - "typescript": ">=4.8.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } + "license": "MIT" }, - "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/utils": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.65.0.tgz", - "integrity": "sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==", + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "@volar/source-map": "2.4.28" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.65.0.tgz", - "integrity": "sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==", + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.65.0", - "@typescript-eslint/tsconfig-utils": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz", - "integrity": "sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==", - "dev": true, + "node_modules/@vue-macros/common": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@vue-macros/common/-/common-3.1.4.tgz", + "integrity": "sha512-/5Fv+6DgIcM9ajY05ZmKBv+LMX1M9A0X+IUwDRVdt67ciw8OV9bvG2r34p3RiEadlsQybjhKPRKNXDC8Bp23cw==", "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.65.0", - "@typescript-eslint/types": "^8.65.0", - "debug": "^4.4.3" + "@vue/compiler-sfc": "^3.5.22", + "ast-kit": "^2.1.2", + "local-pkg": "^1.1.2", + "magic-string-ast": "^1.0.2", + "unplugin-utils": "^0.3.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=20.19.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/vue-macros" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "vue": "^2.7.0 || ^3.2.25" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true + } } }, - "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.65.0.tgz", - "integrity": "sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==", + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", + "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", + "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.2", + "@vue/babel-helper-vue-transform-on": "1.5.0", + "@vue/babel-plugin-resolve-type": "1.5.0", + "@vue/shared": "^3.5.18" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } } }, - "node_modules/@vue/eslint-config-typescript/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", + "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", "dev": true, "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.0", + "@vue/compiler-sfc": "^3.5.18" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/brace-expansion": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", - "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", - "dev": true, + "node_modules/@vue/compiler-core": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.40.tgz", + "integrity": "sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==", "license": "MIT", "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" + "@babel/parser": "^7.29.7", + "@vue/shared": "3.5.40", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/ignore": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", - "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", - "dev": true, + "node_modules/@vue/compiler-dom": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.40.tgz", + "integrity": "sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==", "license": "MIT", - "engines": { - "node": ">= 4" + "dependencies": { + "@vue/compiler-core": "3.5.40", + "@vue/shared": "3.5.40" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", + "node_modules/@vue/compiler-sfc": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.40.tgz", + "integrity": "sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==", + "license": "MIT", "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@babel/parser": "^7.29.7", + "@vue/compiler-core": "3.5.40", + "@vue/compiler-dom": "3.5.40", + "@vue/compiler-ssr": "3.5.40", + "@vue/shared": "3.5.40", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.19", + "source-map-js": "^1.2.1" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/typescript-eslint": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.65.0.tgz", - "integrity": "sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==", - "dev": true, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.40.tgz", + "integrity": "sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==", "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.65.0", - "@typescript-eslint/parser": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/utils": "8.65.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "@vue/compiler-dom": "3.5.40", + "@vue/shared": "3.5.40" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.65.0.tgz", - "integrity": "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==", - "dev": true, + "node_modules/@vue/devtools-api": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.10.tgz", + "integrity": "sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==", "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/type-utils": "8.65.0", - "@typescript-eslint/utils": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.65.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "@vue/devtools-kit": "^7.7.10" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.65.0.tgz", - "integrity": "sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==", + "node_modules/@vue/devtools-core": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.2.1.tgz", + "integrity": "sha512-s/VfAY9oDTb/kFEWmy461jaFde2MIV1RO/gi1vwM+PAZBZ/Pc2Ndu3BNBdZUze8QDUuyYvElbEEGA83syjJfzA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/utils": "8.65.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@vue/devtools-kit": "^8.2.1", + "@vue/devtools-shared": "^8.2.1" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "vue": "^3.0.0" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.65.0.tgz", - "integrity": "sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==", + "node_modules/@vue/devtools-core/node_modules/@vue/devtools-kit": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", + "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/typescript-estree": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "@vue/devtools-shared": "^8.2.1", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "perfect-debounce": "^2.0.0" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.65.0.tgz", - "integrity": "sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==", + "node_modules/@vue/devtools-core/node_modules/@vue/devtools-shared": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", + "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/devtools-core/node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", "dev": true, + "license": "MIT" + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.10.tgz", + "integrity": "sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==", "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.65.0", - "@typescript-eslint/tsconfig-utils": "8.65.0", - "@typescript-eslint/types": "8.65.0", - "@typescript-eslint/visitor-keys": "8.65.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "@vue/devtools-shared": "^7.7.10", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz", - "integrity": "sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==", - "dev": true, + "node_modules/@vue/devtools-shared": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.10.tgz", + "integrity": "sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==", "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.65.0", - "@typescript-eslint/types": "^8.65.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-10.2.0.tgz", + "integrity": "sha512-GL3YBLwv/+b86yHcNNfPJxOTtVFJ4Mbc9UU3zR+KVoG7SwGTjPT+32fXamscNumElhcpXW3mT0DgzS9w32S7Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.2" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "eslint": ">= 8.21.0", + "prettier": ">= 3.0.0" } }, - "node_modules/@vue/eslint-config-typescript/node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.65.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.65.0.tgz", - "integrity": "sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==", + "node_modules/@vue/eslint-config-typescript": { + "version": "14.9.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.9.0.tgz", + "integrity": "sha512-E3j9hDlfVf10F30MRcLTPY2IIhWIx1nsvkVukk14kTcuA+oBVot9zsP1hzsO+PAMDxV3Fd9FimBJtUBNBL5KFA==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.60.0", + "fast-glob": "^3.3.3", + "typescript-eslint": "^8.60.0", + "vue-eslint-parser": "^10.4.0" + }, + "bin": { + "vue-eslint-config-typescript": "dist/bin.js" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "eslint": "^9.10.0 || ^10.0.0", + "eslint-plugin-vue": "^9.28.0 || ^10.0.0", + "typescript": ">=4.8.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@vue/language-core": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.2.6.tgz", - "integrity": "sha512-xYYYX3/aVup576tP/23sEUpgiEnujrENaoNRbaozC1/MA9I6EGFQRJb4xrt/MmUCAGlxTKL2RmT8JLTPqagCkg==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.3.8.tgz", + "integrity": "sha512-ieGT8jJdhhy0mGzStZhsg/qPw5bQZJg5yF+3+XU6saf4sM7yo9ZXy3h+nCwrm2+b4qS/SypkNdR2jAF3uei9tA==", "dev": true, "license": "MIT", "dependencies": { "@volar/language-core": "2.4.28", "@vue/compiler-dom": "^3.5.0", "@vue/shared": "^3.5.0", - "alien-signals": "^3.0.0", + "alien-signals": "^3.2.1", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1", - "picomatch": "^4.0.2" - } - }, - "node_modules/@vue/language-core/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "picomatch": "^4.0.4" } }, "node_modules/@vue/reactivity": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.39.tgz", - "integrity": "sha512-TpsuBJ9gGlZa5d23XcM2y8EXanz9dZeVDQBXRwzy46ItgvM+rWpzs+UVM0wcRLxGvcav0HE5jz2gNL53xlRAog==", + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.40.tgz", + "integrity": "sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.39" + "@vue/shared": "3.5.40" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.39.tgz", - "integrity": "sha512-9GLtNyRvPAUMbX+7ono0RC2j0guo2LXVi8LvcmAooImACUKm0oFf0jjwbX8/H0AE/t1nxhAkn8RSl9PMCzzxZw==", + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.40.tgz", + "integrity": "sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.39", - "@vue/shared": "3.5.39" + "@vue/reactivity": "3.5.40", + "@vue/shared": "3.5.40" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.39.tgz", - "integrity": "sha512-7Y6aAGboKcXAZ3ECuUy7RrS5yy2r47dhTp2SKaJmYxjopImaVFaNa5Ne66NwGovsrxVAl5S5rwc7m22UG7Lmww==", + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.40.tgz", + "integrity": "sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.39", - "@vue/runtime-core": "3.5.39", - "@vue/shared": "3.5.39", + "@vue/reactivity": "3.5.40", + "@vue/runtime-core": "3.5.40", + "@vue/shared": "3.5.40", "csstype": "^3.2.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.39.tgz", - "integrity": "sha512-yZSakiAGw85rZfG7UM8akMnIF+FmeiNk47uvHf2nVBBSe+dIKUhZuZq9+XgJhbV3nS5Z4ALH23/MpXofW+mbcw==", + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.40.tgz", + "integrity": "sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.39", - "@vue/shared": "3.5.39" - }, - "peerDependencies": { - "vue": "3.5.39" + "@vue/compiler-ssr": "3.5.40", + "@vue/runtime-dom": "3.5.40", + "@vue/shared": "3.5.40" } }, "node_modules/@vue/shared": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.39.tgz", - "integrity": "sha512-l1rrBtBfTnmxvtsvdQDXltUUy8S1Y+ZaqdfUzmAnJkTd8Z8rv5v/ytW+TKiqEOWyHPoqtPlNFSs0lhRmYVSHVA==", + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.40.tgz", + "integrity": "sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==", "license": "MIT" }, "node_modules/@vue/test-utils": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz", - "integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==", + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.11.tgz", + "integrity": "sha512-GDqaqZsA6m2E5vNzej0aYiIb6BX8xV9pNSbbbXKOfEYwg7ZNblVX8suyqmUBThq8VIrgAJNxn+z72hVtUeiWHA==", "dev": true, "license": "MIT", "dependencies": { "js-beautify": "^1.14.9", - "vue-component-type-helpers": "^2.0.0" + "vue-component-type-helpers": "^3.0.0" + }, + "peerDependencies": { + "@vue/compiler-dom": "3.x", + "@vue/server-renderer": "3.x", + "vue": "3.x" + }, + "peerDependenciesMeta": { + "@vue/server-renderer": { + "optional": true + } } }, "node_modules/@vue/tsconfig": { @@ -5698,27 +4516,15 @@ } }, "node_modules/@vueuse/core": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.9.0.tgz", - "integrity": "sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.3.0.tgz", + "integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==", "license": "MIT", "dependencies": { "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "13.9.0", - "@vueuse/shared": "13.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "@vueuse/metadata": "14.3.0", + "@vueuse/shared": "14.3.0" }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/@vueuse/core/node_modules/@vueuse/shared": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.9.0.tgz", - "integrity": "sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" }, @@ -5727,14 +4533,14 @@ } }, "node_modules/@vueuse/integrations": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-14.2.1.tgz", - "integrity": "sha512-2LIUpBi/67PoXJGqSDQUF0pgQWpNHh7beiA+KG2AbybcNm+pTGWT6oPGlBgUoDWmYwfeQqM/uzOHqcILpKL7nA==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-14.3.0.tgz", + "integrity": "sha512-76I5FT2ESvCmCaSwapI+a/u/CFtNXmzl9f9lNp1hRtx8vKB8hfiokJr8IvQqcQG5ckGXElyXK516b54ozV3MvA==", "dev": true, "license": "MIT", "dependencies": { - "@vueuse/core": "14.2.1", - "@vueuse/shared": "14.2.1" + "@vueuse/core": "14.3.0", + "@vueuse/shared": "14.3.0" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -5793,47 +4599,19 @@ } } }, - "node_modules/@vueuse/integrations/node_modules/@vueuse/core": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.1.tgz", - "integrity": "sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "14.2.1", - "@vueuse/shared": "14.2.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/@vueuse/integrations/node_modules/@vueuse/metadata": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.2.1.tgz", - "integrity": "sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@vueuse/metadata": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.9.0.tgz", - "integrity": "sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.3.0.tgz", + "integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.2.1.tgz", - "integrity": "sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.3.0.tgz", + "integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" @@ -5860,6 +4638,8 @@ }, "node_modules/abbrev": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "dev": true, "license": "ISC", "engines": { @@ -5867,9 +4647,9 @@ } }, "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -5880,6 +4660,8 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5909,45 +4691,42 @@ } }, "node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", - "dev": true, + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/alien-signals": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.1.2.tgz", - "integrity": "sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/ansi-escapes": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", - "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", - "dev": true, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", "license": "MIT", - "dependencies": { - "environment": "^1.0.0" - }, - "engines": { - "node": ">=18" + "peerDependencies": { + "ajv": "^8.5.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, + "node_modules/alien-signals": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.2.1.tgz", + "integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", @@ -5962,23 +4741,22 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/ansis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", - "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.3.1.tgz", + "integrity": "sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==", "dev": true, "license": "ISC", "engines": { @@ -5987,10 +4765,14 @@ }, "node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, "node_modules/aria-hidden": { "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" @@ -6026,13 +4808,14 @@ } }, "node_modules/ast-walker-scope": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.8.3.tgz", - "integrity": "sha512-cbdCP0PGOBq0ASG+sjnKIoYkWMKhhz+F/h9pRexUdX2Hd38+WOlBkRKlqkGOSm0YQpcFMQBJeK4WspUAkwsEdg==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.9.0.tgz", + "integrity": "sha512-IJdzo2vLiElBxKzwS36VsCue/62d6IdWjnPB2v3nuPKeWGynp6FF/CYoLa5i/3jXH/z97ZDdsXz6abpgM6w07A==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.4", - "ast-kit": "^2.1.3" + "@babel/parser": "^7.29.2", + "@babel/types": "^7.29.0", + "ast-kit": "^2.2.0" }, "engines": { "node": ">=20.19.0" @@ -6048,9 +4831,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", - "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", "license": "MIT", "dependencies": { "follow-redirects": "^1.16.0", @@ -6059,30 +4842,6 @@ "proxy-from-env": "^2.1.0" } }, - "node_modules/axios/node_modules/proxy-from-env": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", - "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/b4a": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", - "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", - "dev": true, - "license": "Apache-2.0", - "peerDependencies": { - "react-native-b4a": "*" - }, - "peerDependenciesMeta": { - "react-native-b4a": { - "optional": true - } - } - }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -6100,105 +4859,13 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/bare-events": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.3.tgz", - "integrity": "sha512-HdUm8EMQBLaJvGUdidNNbqpA1kYkwNcb+MYxkxCLAPJGQzlv9J0C24h8V65Z4c5GLd/JEALDvpFCQgpLJqc0zw==", - "dev": true, - "license": "Apache-2.0", - "peerDependencies": { - "bare-abort-controller": "*" - }, - "peerDependenciesMeta": { - "bare-abort-controller": { - "optional": true - } - } - }, - "node_modules/bare-fs": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.1.tgz", - "integrity": "sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.5.4", - "bare-path": "^3.0.0", - "bare-stream": "^2.6.4", - "bare-url": "^2.2.2", - "fast-fifo": "^1.3.2" - }, - "engines": { - "bare": ">=1.16.0" - }, - "peerDependencies": { - "bare-buffer": "*" - }, - "peerDependenciesMeta": { - "bare-buffer": { - "optional": true - } - } - }, - "node_modules/bare-os": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.9.1.tgz", - "integrity": "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "bare": ">=1.14.0" - } - }, - "node_modules/bare-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", - "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bare-os": "^3.0.1" - } - }, - "node_modules/bare-stream": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.1.tgz", - "integrity": "sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "streamx": "^2.25.0", - "teex": "^1.0.1" - }, - "peerDependencies": { - "bare-abort-controller": "*", - "bare-buffer": "*", - "bare-events": "*" - }, - "peerDependenciesMeta": { - "bare-abort-controller": { - "optional": true - }, - "bare-buffer": { - "optional": true - }, - "bare-events": { - "optional": true - } - } - }, - "node_modules/bare-url": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.3.tgz", - "integrity": "sha512-Kccpc7ACfXaxfeInfqKcZtW4pT5YBn1mesc4sCsun6sRwtbJ4h+sNOaksUpYEJUKfN65YWC6Bw2OJEFiKxq8nQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bare-path": "^3.0.0" + "node": "18 || 20 || >=22" } }, "node_modules/base64-arraybuffer": { @@ -6210,6 +4877,18 @@ "node": ">= 0.6.0" } }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.4.tgz", + "integrity": "sha512-s4+sLr9mZ/CyqeRritFeYV/Zx73OAtmaHn6kkBS1XRoJn1hrg3xIDUcpicAEX68tkcIN0iBCgti31C8zxtkhsQ==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/birpc": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", @@ -6221,21 +4900,28 @@ }, "node_modules/boolbase": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true, "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", + "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" } }, "node_modules/braces": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { @@ -6246,7 +4932,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.0", + "version": "4.28.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz", + "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==", "funding": [ { "type": "opencollective", @@ -6263,10 +4951,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001718", - "electron-to-chromium": "^1.5.160", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.10.44", + "caniuse-lite": "^1.0.30001806", + "electron-to-chromium": "^1.5.393", + "node-releases": "^2.0.51", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -6275,6 +4964,19 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-image-size": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/buffer-image-size/-/buffer-image-size-0.6.4.tgz", + "integrity": "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/bundle-name": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", @@ -6293,6 +4995,8 @@ }, "node_modules/cac": { "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "license": "MIT", "engines": { "node": ">=8" @@ -6300,6 +5004,8 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -6311,6 +5017,8 @@ }, "node_modules/call-bound": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -6325,17 +5033,24 @@ }, "node_modules/call-me-maybe": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", "license": "MIT" }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001724", + "version": "1.0.30001806", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", "funding": [ { "type": "opencollective", @@ -6375,6 +5090,8 @@ }, "node_modules/character-entities": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "license": "MIT", "funding": { "type": "github", @@ -6441,128 +5158,65 @@ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", "license": "Apache-2.0", "dependencies": { - "clsx": "^2.1.1" - }, - "funding": { - "url": "https://polar.sh/cva" - } - }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", - "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^8.0.0", - "string-width": "^8.2.0" - }, - "engines": { - "node": ">=20" + "clsx": "^2.1.1" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://polar.sh/cva" } }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dev": true, "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "node": ">=20" } }, "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, "license": "MIT" }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" + "node": ">=18" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -6602,6 +5256,8 @@ }, "node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6613,6 +5269,8 @@ }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, @@ -6639,6 +5297,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/confbox": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", @@ -6647,6 +5315,8 @@ }, "node_modules/config-chain": { "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6655,17 +5325,22 @@ } }, "node_modules/convert-source-map": { - "version": "2.0.0", - "license": "MIT" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT", + "peer": true }, "node_modules/copy-anything": { - "version": "3.0.5", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", "license": "MIT", "dependencies": { - "is-what": "^4.1.8" + "is-what": "^5.2.0" }, "engines": { - "node": ">=12.13" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/mesqueeb" @@ -6700,6 +5375,8 @@ }, "node_modules/cross-spawn": { "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -6720,6 +5397,8 @@ }, "node_modules/cssesc": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -6922,16 +5601,6 @@ "node": ">=12" } }, - "node_modules/d3-dsv/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 10" - } - }, "node_modules/d3-ease": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", @@ -7015,694 +5684,1220 @@ "node": ">=12" } }, - "node_modules/d3-geo-projection/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "peer": true, + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate-path": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-interpolate-path/-/d3-interpolate-path-2.3.0.tgz", + "integrity": "sha512-tZYtGXxBmbgHsIc9Wms6LS5u4w6KbP8C09a4/ZYc4KLMYYqub57rRBUgpUr2CIarIrJEpdAWWxWQvofgaMpbKQ==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC", + "peer": true + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "peer": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", "peer": true, "engines": { - "node": ">= 10" + "node": ">=12" } }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", "license": "ISC", "peer": true, + "dependencies": { + "d3-path": "^3.1.0" + }, "engines": { "node": ">=12" } }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", "license": "ISC", "peer": true, "dependencies": { - "d3-color": "1 - 3" + "d3-array": "2 - 3" }, "engines": { "node": ">=12" } }, - "node_modules/d3-interpolate-path": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-interpolate-path/-/d3-interpolate-path-2.3.0.tgz", - "integrity": "sha512-tZYtGXxBmbgHsIc9Wms6LS5u4w6KbP8C09a4/ZYc4KLMYYqub57rRBUgpUr2CIarIrJEpdAWWxWQvofgaMpbKQ==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", "license": "ISC", "peer": true, + "dependencies": { + "d3-time": "1 - 3" + }, "engines": { "node": ">=12" } }, - "node_modules/d3-polygon": { + "node_modules/d3-timer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", "license": "ISC", "peer": true, "engines": { "node": ">=12" } }, - "node_modules/d3-quadtree": { + "node_modules/d3-transition": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", "license": "ISC", "peer": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, "engines": { "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" } }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", "license": "ISC", "peer": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, "engines": { "node": ">=12" } }, - "node_modules/d3-sankey": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", - "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", - "license": "BSD-3-Clause", - "peer": true, + "node_modules/date-fns": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.4.0.tgz", + "integrity": "sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/date-fns-tz": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.2.0.tgz", + "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==", + "license": "MIT", + "peerDependencies": { + "date-fns": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "d3-array": "1 - 2", - "d3-shape": "^1.2.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/d3-sankey/node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "license": "BSD-3-Clause", - "peer": true, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "license": "MIT", "dependencies": { - "internmap": "^1.0.0" + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/d3-sankey/node_modules/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", - "license": "BSD-3-Clause", - "peer": true + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" }, - "node_modules/d3-sankey/node_modules/d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "license": "BSD-3-Clause", - "peer": true, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-path": "1" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-sankey/node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", - "license": "ISC", - "peer": true + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/delaunator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", + "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", "license": "ISC", "peer": true, "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" + "robust-predicates": "^3.0.2" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1638949", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1638949.tgz", + "integrity": "sha512-mXwg4Fqnv0WR4iuAT/gYUmctNkjILwXFHyZ+m7Ty1dfr0ezZt2U3gnrrJTfRobJTHoXf+IbuFvFITzLrLFjwJA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/diff": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "license": "BSD-3-Clause", "engines": { - "node": ">=12" + "node": ">=0.3.1" } }, - "node_modules/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" + "node_modules/dompurify": { + "version": "3.4.12", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.12.tgz", + "integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" } }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "peer": true, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "peer": true, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { - "d3-path": "^3.1.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=12" + "node": ">= 0.4" } }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "node_modules/earcut": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", "license": "ISC", - "peer": true, + "peer": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/editorconfig": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.7.tgz", + "integrity": "sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "2 - 3" + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "^9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" }, "engines": { - "node": ">=12" + "node": ">=14" } }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "peer": true, + "node_modules/editorconfig/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", + "dev": true, + "license": "MIT", "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" + "balanced-match": "^1.0.0" } }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "peer": true, + "node_modules/editorconfig/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=14" } }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, "license": "ISC", - "peer": true, "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" + "brace-expansion": "^2.0.2" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" }, - "peerDependencies": { - "d3-selection": "2 - 3" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "peer": true, + "node_modules/electron-to-chromium": { + "version": "1.5.396", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.396.tgz", + "integrity": "sha512-yHiw2Y3C3H9U6TMbOfoWK/BPreiOPXRfTWPBwQBoZG6/8TB6eOPnsy5oaRYuatR7Fw2SJ4kKforgufeo7fq0EQ==", + "license": "ISC" + }, + "node_modules/elkjs": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.10.2.tgz", + "integrity": "sha512-Yx3ORtbAFrXelYkAy2g0eYyVY8QG0XEmGdQXmy0eithKKjbWRfl3Xe884lfkszfBF6UKyIy4LwfcZ3AZc8oxFw==", + "license": "EPL-2.0", + "peer": true + }, + "node_modules/emoji-picker-element": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/emoji-picker-element/-/emoji-picker-element-1.12.1.tgz", + "integrity": "sha512-F9AY/re8uqZmBcCXLHLGvyy7fxuMQdZl9R8OToLRH8Vnns+WMX8RYUbI2nSJklzl5+82qzpYWeus1/puDepWcQ==", + "license": "Apache-2.0" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.24.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.3.tgz", + "integrity": "sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ==", + "license": "MIT", "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" }, "engines": { - "node": ">=12" + "node": ">=10.13.0" } }, - "node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, "license": "MIT", "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/date-fns-tz": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.2.0.tgz", - "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==", + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "peerDependencies": { - "date-fns": "^3.0.0 || ^4.0.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/dayjs": { - "version": "1.11.20", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", - "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "dev": true, "license": "MIT" }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "devOptional": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "ms": "^2.1.3" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=6.0" + "node": ">=18" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" } }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/default-browser": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", - "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "node_modules/eslint": { + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.0.tgz", + "integrity": "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==", "dev": true, "license": "MIT", + "workspaces": [ + "packages/*" + ], "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/default-browser-id": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", - "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "node_modules/eslint-plugin-prettier": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.6.tgz", + "integrity": "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==", "dev": true, "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.13" + }, "engines": { - "node": ">=12" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/defu": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.6.tgz", - "integrity": "sha512-f8mefEW4WIVg4LckePx3mALjQSPQgFlg9U8yaPdlsbdYcHQyj9n2zL2LJEA52smeYxOvmd/nB7TpMtHGMTHcug==", - "license": "MIT" - }, - "node_modules/delaunator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", - "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", - "license": "ISC", - "peer": true, + "node_modules/eslint-plugin-vue": { + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.10.0.tgz", + "integrity": "sha512-dL9x9rBHqqNcByWiLOHK6L0SB97V82/NC0cZRn9cXPjM7pCuWlpQQP9bFH4vjBv80ej1ZpzAkuD8zWH1o9bZbA==", + "dev": true, + "license": "MIT", "dependencies": { - "robust-predicates": "^3.0.2" + "@eslint-community/eslint-utils": "^4.9.1", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^7.1.4", + "semver": "^7.8.5", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "vue-eslint-parser": "^10.3.0" + }, + "peerDependenciesMeta": { + "@stylistic/eslint-plugin": { + "optional": true + }, + "@typescript-eslint/parser": { + "optional": true + } } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/eslint-plugin-vue/node_modules/postcss-selector-parser": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz", + "integrity": "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==", + "dev": true, "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, "engines": { - "node": ">=0.4.0" + "node": ">=4" } }, - "node_modules/dequal": { - "version": "2.0.3", - "license": "MIT", + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=6" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/detect-libc": { - "version": "2.0.4", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "node_modules/eslint/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { - "dequal": "^2.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/devtools-protocol": { - "version": "0.0.1608973", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1608973.tgz", - "integrity": "sha512-Tpm17fxYzt+J7VrGdc1k8YdRqS3YV7se/M6KeemEqvUbq/n7At1rWVuXMxQgpWkdwSdIEKYbU//Bve+Shm4YNQ==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, - "node_modules/diff": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", - "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", - "license": "BSD-3-Clause", + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">= 4" } }, - "node_modules/dompurify": { - "version": "3.4.11", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz", - "integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/dotenv": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", - "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "license": "BSD-2-Clause", + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://dotenvx.com" + "url": "https://opencollective.com/eslint" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "license": "MIT", + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "estraverse": "^5.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10" } }, - "node_modules/earcut": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", - "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", - "license": "ISC", - "peer": true - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/editorconfig": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.7.tgz", - "integrity": "sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@one-ini/wasm": "0.1.1", - "commander": "^10.0.0", - "minimatch": "^9.0.1", - "semver": "^7.5.3" - }, - "bin": { - "editorconfig": "bin/editorconfig" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=14" + "node": ">=4.0" } }, - "node_modules/editorconfig/node_modules/commander": { - "version": "10.0.1", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=14" + "node": ">=4.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.171", - "license": "ISC" + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" }, - "node_modules/elkjs": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.10.2.tgz", - "integrity": "sha512-Yx3ORtbAFrXelYkAy2g0eYyVY8QG0XEmGdQXmy0eithKKjbWRfl3Xe884lfkszfBF6UKyIy4LwfcZ3AZc8oxFw==", - "license": "EPL-2.0", - "peer": true + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/emoji-picker-element": { - "version": "1.12.1", - "license": "Apache-2.0" + "node_modules/eval-estree-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eval-estree-expression/-/eval-estree-expression-3.0.1.tgz", + "integrity": "sha512-zTLKGbiVdQYp4rQkSoXPibrFf5ZoPn6jzExegRLEQ13F+FSxu5iLgaRH6hlDs2kWSUa6vp8yD20cdJi0me6pEw==", + "license": "MIT" }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, + "node_modules/event-source-polyfill": { + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.31.tgz", + "integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==", + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "license": "MIT" }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.21.6", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", - "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", + "node_modules/exsolve": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.1.0.tgz", + "integrity": "sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, "engines": { - "node": ">=10.13.0" + "node": ">=8.6.0" } }, - "node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "engines": { + "node": ">= 6" } }, - "node_modules/env-paths": { - "version": "2.2.1", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/error-ex": { - "version": "1.3.2", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } + "node_modules/fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/error-stack-parser-es": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", - "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.4" + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/es-errors": { - "version": "1.3.0", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "dev": true, + "node_modules/fflate": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.9.tgz", + "integrity": "sha512-zdxgIEddhfsyCaWpJ2SdXEP8ZMrKJ6+5jl4OupODcywU0IhRk6gdXuVGcPICyfx2H97hVK7xmJtRLPjkxAX8Vw==", "license": "MIT" }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=16.0.0" } }, - "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", - "devOptional": true, - "hasInstallScript": true, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "dependencies": { + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "node": ">=8" } }, - "node_modules/escalade": { - "version": "3.2.0", + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", "license": "MIT", - "engines": { - "node": ">=6" - } + "peer": true }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=10" }, @@ -7710,627 +6905,606 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.7.0.tgz", - "integrity": "sha512-GVTD7s1vdIl6UYvAfriOPeY1Df8LIZjfofLvHwde+erDHGGuHyuM6xoxRxmHiebhYuD2p1vN4wWh0XzPARSGDQ==", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", - "workspaces": [ - "packages/*" - ], "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.2", - "@eslint/config-array": "^0.23.5", - "@eslint/config-helpers": "^0.6.0", - "@eslint/core": "^1.2.1", - "@eslint/plugin-kit": "^0.7.2", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.14.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^9.1.2", - "eslint-visitor-keys": "^5.0.1", - "espree": "^11.2.0", - "esquery": "^1.7.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "minimatch": "^10.2.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } + "node": ">=16" } }, - "node_modules/eslint-config-prettier": { - "version": "10.1.5", + "node_modules/flatted": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.3.tgz", + "integrity": "sha512-/zipXxyO6rGvuNGDiULY9MvEGSkb2gaG4GGH4ygMi0ZZzyMHdUZBmntJmx5x1G2VuPytCwGN4xsJP6cw+sK+vQ==", "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "funding": { - "url": "https://opencollective.com/eslint-config-prettier" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } + "license": "ISC" }, - "node_modules/eslint-plugin-prettier": { - "version": "5.5.0", + "node_modules/focus-trap": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-8.2.2.tgz", + "integrity": "sha512-qV0g8hRYBqgACcFOH3f9wXc4zPKhr/0z9RI2a6ZijZ72EeBi4g8oBy8zAWuUR1TsMpOzwpUMFvjdasrC41Joug==", "dev": true, "license": "MIT", "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.11.7" - }, + "tabbable": "^6.5.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", - "prettier": ">=3.0.0" + "node": ">=4.0" }, "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { + "debug": { "optional": true } } }, - "node_modules/eslint-plugin-vue": { - "version": "10.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.8.0.tgz", - "integrity": "sha512-f1J/tcbnrpgC8suPN5AtdJ5MQjuXbSU9pGRSSYAuF3SHoiYCOdEX6O22pLaRyLHXvDcOe+O5ENgc1owQ587agA==", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.1.1", - "postcss-selector-parser": "^7.1.0", - "semver": "^7.6.3", - "xml-name-validator": "^4.0.0" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", - "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "vue-eslint-parser": "^10.0.0" + "node": ">=14" }, - "peerDependenciesMeta": { - "@stylistic/eslint-plugin": { - "optional": true - }, - "@typescript-eslint/parser": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint-scope": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", - "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">=12" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "license": "Apache-2.0", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "license": "MIT", "engines": { - "node": "18 || 20 || >=22" + "node": ">=6.9.0" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, + "node_modules/geojson": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/geojson/-/geojson-0.5.0.tgz", + "integrity": "sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ==", "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, + "peer": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/geojson-vt": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz", + "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==", + "license": "ISC", + "peer": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", "engines": { - "node": "18 || 20 || >=22" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { - "brace-expansion": "^5.0.5" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": "18 || 20 || >=22" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/espree": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", - "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { - "acorn": "^8.16.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^5.0.1" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 0.4" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", - "dev": true, - "license": "Apache-2.0", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "peer": true, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "node_modules/gl-matrix": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", + "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", + "license": "MIT", + "peer": true + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "BSD-3-Clause", + "license": "ISC", "dependencies": { - "estraverse": "^5.1.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=0.10" + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/esrecurse": { - "version": "4.3.0", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", "dependencies": { - "estraverse": "^5.2.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" + "node": ">=10.13.0" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "license": "MIT" - }, - "node_modules/esutils": { - "version": "2.0.3", + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eval-estree-expression": { - "version": "2.1.1", - "license": "MIT" - }, - "node_modules/event-source-polyfill": { - "version": "1.0.31", - "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.31.tgz", - "integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==", "license": "MIT" }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "license": "MIT" - }, - "node_modules/events-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", - "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "bare-events": "^2.7.0" + "balanced-match": "^1.0.0" } }, - "node_modules/expect-type": { - "version": "1.3.0", + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, "engines": { - "node": ">=12.0.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/exsolve": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", - "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "license": "MIT" - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "license": "Apache-2.0" - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "dev": true, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "license": "MIT", + "peer": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" }, "engines": { - "node": ">=8.6.0" + "node": ">=6" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "license": "ISC", + "peer": true, "dependencies": { - "is-glob": "^4.0.1" + "isexe": "^2.0.0" }, - "engines": { - "node": ">= 6" + "bin": { + "which": "bin/which" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastq": { - "version": "1.19.1", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fflate": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.9.tgz", - "integrity": "sha512-zdxgIEddhfsyCaWpJ2SdXEP8ZMrKJ6+5jl4OupODcywU0IhRk6gdXuVGcPICyfx2H97hVK7xmJtRLPjkxAX8Vw==", - "license": "MIT" + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "dev": true, + "node_modules/handlebars": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "license": "MIT", "dependencies": { - "flat-cache": "^4.0.0" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": ">=16.0.0" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/fill-range": { - "version": "7.1.1", + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/happy-dom": { + "version": "20.11.1", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.11.1.tgz", + "integrity": "sha512-XSt8tMzbW9ymE7687xztkO1ckR7qJNQ3LywY9vlYGhGi3zXrGBHuUo2Cl1ztZaICW+1eAGdkLbj6iwVqDT33kg==", "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "@types/node": ">=20.0.0", + "@types/whatwg-mimetype": "^3.0.2", + "@types/ws": "^8.18.1", + "buffer-image-size": "^0.6.4", + "entities": "^7.0.1", + "whatwg-mimetype": "^3.0.0", + "ws": "^8.21.0" }, "engines": { - "node": ">=8" + "node": ">=20.0.0" } }, - "node_modules/find-root": { + "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", - "peer": true + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/find-up": { - "version": "5.0.0", - "dev": true, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "has-symbols": "^1.0.3" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "dev": true, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "function-bind": "^1.1.2" }, "engines": { - "node": ">=16" + "node": ">= 0.4" } }, - "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", - "dev": true, - "license": "ISC" - }, - "node_modules/focus-trap": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-8.0.1.tgz", - "integrity": "sha512-9ptSG6z51YQOstI/oN4XuVGP/03u2nh0g//qz7L6zX0i6PZiPnkcf3GenXq7N2hZnASXaMxTPpbKwdI+PFvxlw==", + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", "dev": true, "license": "MIT", "dependencies": { - "tabbable": "^6.4.0" + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/follow-redirects": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", - "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=4.0" + "dependencies": { + "@types/hast": "^3.0.0" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/foreground-child": { - "version": "3.3.1", + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/form-data": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", - "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.4", - "mime-types": "^2.1.35" + "agent-base": "6", + "debug": "4" }, "engines": { "node": ">= 6" } }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=0.10.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "peer": true }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", + "node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">= 4" } }, - "node_modules/geojson": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/geojson/-/geojson-0.5.0.tgz", - "integrity": "sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ==", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "license": "MIT", "peer": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, "engines": { - "node": ">= 0.10" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/geojson-vt": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz", - "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==", - "license": "ISC", - "peer": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", "license": "ISC", + "peer": true, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=12" } }, - "node_modules/get-east-asian-width": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", - "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", - "dev": true, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "peer": true }, - "node_modules/get-intrinsic": { - "version": "1.3.0", + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "license": "MIT", + "peer": true, "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "hasown": "^2.0.3" }, "engines": { "node": ">= 0.4" @@ -8339,1211 +7513,1798 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-proto": { - "version": "1.0.1", + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-tsconfig": { - "version": "4.13.0", - "devOptional": true, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/gl-matrix": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", - "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", - "peer": true + "engines": { + "node": ">=8" + } }, - "node_modules/glob": { - "version": "10.5.0", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "is-extglob": "^2.1.1" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-in-ssh": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", + "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/glob-parent": { - "version": "6.0.2", + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" }, "engines": { - "node": ">=10.13.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, "engines": { - "node": ">=6" + "node": ">=0.12.0" } }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "license": "ISC", - "peer": true, - "dependencies": { - "isexe": "^2.0.0" + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "license": "MIT", + "engines": { + "node": ">=18" }, - "bin": { - "which": "bin/which" + "funding": { + "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/gopd": { - "version": "1.2.0", + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=16" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, - "node_modules/handlebars": { - "version": "4.7.9", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", - "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", - "license": "MIT", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=0.4.7" + "funding": { + "url": "https://github.com/sponsors/isaacs" }, "optionalDependencies": { - "uglify-js": "^3.1.4" + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/happy-dom": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-20.8.9.tgz", - "integrity": "sha512-Tz23LR9T9jOGVZm2x1EPdXqwA37G/owYMxRwU0E4miurAtFsPMQ1d2Jc2okUaSjZqAFz2oEn3FLXC5a0a+siyA==", + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-beautify": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": ">=20.0.0", - "@types/whatwg-mimetype": "^3.0.2", - "@types/ws": "^8.18.1", - "entities": "^7.0.1", - "whatwg-mimetype": "^3.0.0", - "ws": "^8.18.3" + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^7.2.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" }, "engines": { - "node": ">=20.0.0" + "node": ">=14" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/js-cookie": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.8.tgz", + "integrity": "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==", + "license": "MIT" }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": ">= 0.4" + "node": ">=6" } }, - "node_modules/hast-util-to-html": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", - "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" + "peer": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6" } }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dev": true, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0" + "universalify": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/hookable": { - "version": "5.5.3", - "license": "MIT" - }, - "node_modules/html-void-elements": { + "node_modules/kdbush": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", + "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==", + "license": "ISC", + "peer": true + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "json-buffer": "3.0.1" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, + "peer": true, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "license": "MIT", - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause", + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/leaflet": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.7.1.tgz", + "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==", + "license": "BSD-2-Clause", "peer": true }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, "engines": { - "node": ">= 4" + "node": ">= 0.8.0" } }, - "node_modules/import-fresh": { - "version": "3.3.1", - "license": "MIT", + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "license": "MPL-2.0", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "detect-libc": "^2.0.3" }, "engines": { - "node": ">=6" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=0.8.19" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/ini": { - "version": "1.3.8", - "license": "ISC" + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "peer": true, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "license": "MIT" - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "license": "MIT", - "peer": true, - "dependencies": { - "hasown": "^2.0.2" - }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 0.4" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14.16" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.12.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-what": { - "version": "4.1.16", - "license": "MIT", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.13" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/mesqueeb" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/is-wsl": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", - "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, "engines": { - "node": ">=16" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/isexe": { - "version": "2.0.0", - "license": "ISC" + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT", + "peer": true }, - "node_modules/jackspeak": { - "version": "3.4.3", + "node_modules/lint-staged": { + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.2.0.tgz", + "integrity": "sha512-FchGnFe4i4B1C/a35SPU9bNGPEHSC1+1iV0plLjzBmKVe9klZrlRfSgK6Cw4VeHyqOXbJUXP0vON61uRftNQ0A==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "picomatch": "^4.0.5", + "string-argv": "^0.3.2", + "tinyexec": "^1.2.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=22.22.1" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/lint-staged" }, "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "yaml": "^2.9.0" } }, - "node_modules/jiti": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "node_modules/local-pkg": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.2.1.tgz", + "integrity": "sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==", "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/js-beautify": { - "version": "1.15.4", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { - "config-chain": "^1.1.13", - "editorconfig": "^1.0.4", - "glob": "^10.4.2", - "js-cookie": "^3.0.5", - "nopt": "^7.2.1" - }, - "bin": { - "css-beautify": "js/bin/css-beautify.js", - "html-beautify": "js/bin/html-beautify.js", - "js-beautify": "js/bin/js-beautify.js" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=14" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/js-cookie": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.8.tgz", - "integrity": "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==", + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", "license": "MIT" }, - "node_modules/js-tokens": { - "version": "4.0.0", + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", "license": "MIT" }, - "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "MIT", + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "yallist": "^3.0.2" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" + "node_modules/lucide-vue-next": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-1.0.0.tgz", + "integrity": "sha512-V6SPvx1IHTj/UY+FrIYWV5faISsPSb8BnWSFDxAtezWKvWc9ZZ40PDrdu1/Qb5vg4lHWr1hs1BAMGVGm6V1Xdg==", + "deprecated": "Package deprecated. Please use @lucide/vue instead.", + "license": "ISC", + "peerDependencies": { + "vue": ">=3.0.1" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "dev": true, - "license": "MIT" + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } }, - "node_modules/json-parse-even-better-errors": { - "version": "4.0.0", - "dev": true, + "node_modules/magic-string-ast": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/magic-string-ast/-/magic-string-ast-1.0.3.tgz", + "integrity": "sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==", "license": "MIT", + "dependencies": { + "magic-string": "^0.30.19" + }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" } }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" + "node_modules/maplibre-gl": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-2.4.0.tgz", + "integrity": "sha512-csNFylzntPmHWidczfgCZpvbTSmhaWvLRj9e1ezUDBEPizGgshgm3ea1T5TCNEEBq0roauu7BPuRZjA3wO4KqA==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@mapbox/geojson-rewind": "^0.5.2", + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/mapbox-gl-supported": "^2.0.1", + "@mapbox/point-geometry": "^0.1.0", + "@mapbox/tiny-sdf": "^2.0.5", + "@mapbox/unitbezier": "^0.0.1", + "@mapbox/vector-tile": "^1.3.1", + "@mapbox/whoots-js": "^3.1.0", + "@types/geojson": "^7946.0.10", + "@types/mapbox__point-geometry": "^0.1.2", + "@types/mapbox__vector-tile": "^1.3.0", + "@types/pbf": "^3.0.2", + "csscolorparser": "~1.0.3", + "earcut": "^2.2.4", + "geojson-vt": "^3.2.1", + "gl-matrix": "^3.4.3", + "global-prefix": "^3.0.0", + "murmurhash-js": "^1.0.0", + "pbf": "^3.2.1", + "potpack": "^1.0.2", + "quickselect": "^2.0.0", + "supercluster": "^7.1.5", + "tinyqueue": "^2.0.3", + "vt-pbf": "^3.1.3" + } }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", "dev": true, "license": "MIT" }, - "node_modules/json5": { - "version": "2.2.3", + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/jsonfile": { - "version": "6.1.0", + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, "license": "MIT", "dependencies": { - "universalify": "^2.0.0" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/kdbush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", - "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==", - "license": "ISC", - "peer": true + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } }, - "node_modules/keyv": { - "version": "4.5.4", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", + "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "micromark-core-commonmark": "^1.0.1", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/micromark-core-commonmark": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", + "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-factory-destination": "^1.0.0", + "micromark-factory-label": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-factory-title": "^1.0.0", + "micromark-factory-whitespace": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-html-tag-name": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" } }, - "node_modules/kleur": { - "version": "4.1.5", + "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/kolorist": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", - "dev": true, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT" }, - "node_modules/leaflet": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.7.1.tgz", - "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==", - "license": "BSD-2-Clause", - "peer": true + "node_modules/micromark-core-commonmark/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, + "node_modules/micromark-extension-gfm": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz", + "integrity": "sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==", "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lightningcss": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", - "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.30.2", - "lightningcss-darwin-arm64": "1.30.2", - "lightningcss-darwin-x64": "1.30.2", - "lightningcss-freebsd-x64": "1.30.2", - "lightningcss-linux-arm-gnueabihf": "1.30.2", - "lightningcss-linux-arm64-gnu": "1.30.2", - "lightningcss-linux-arm64-musl": "1.30.2", - "lightningcss-linux-x64-gnu": "1.30.2", - "lightningcss-linux-x64-musl": "1.30.2", - "lightningcss-win32-arm64-msvc": "1.30.2", - "lightningcss-win32-x64-msvc": "1.30.2" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", - "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" + "micromark-extension-gfm-autolink-literal": "^1.0.0", + "micromark-extension-gfm-footnote": "^1.0.0", + "micromark-extension-gfm-strikethrough": "^1.0.0", + "micromark-extension-gfm-table": "^1.0.0", + "micromark-extension-gfm-tagfilter": "^1.0.0", + "micromark-extension-gfm-task-list-item": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-types": "^1.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/unified" } }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", - "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz", + "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/unified" } }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", - "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", - "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "license": "MIT" }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", - "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" } }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", - "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "license": "MIT" }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", - "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz", + "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", + "license": "MIT", + "dependencies": { + "micromark-core-commonmark": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/unified" } }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", - "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", - "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", - "cpu": [ - "x64" + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" } }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", - "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", - "cpu": [ - "arm64" + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz", + "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/unified" } }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.2", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", - "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "license": "MIT" }, - "node_modules/lines-and-columns": { - "version": "1.2.4", + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT" }, - "node_modules/lint-staged": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.0.3.tgz", - "integrity": "sha512-wnvMRhzC3GNpjixxleiG+pAW09dHTUgBCjMS7XouAg5E7wKUc8YdfogpF7zIgvXKDbH+452O6+XpnKm6V67rPw==", - "dev": true, + "node_modules/micromark-extension-gfm-table": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz", + "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", "license": "MIT", "dependencies": { - "listr2": "^10.2.1", - "picomatch": "^4.0.4", - "string-argv": "^0.3.2", - "tinyexec": "^1.1.2" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": ">=22.22.1" + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" }, "funding": { - "url": "https://opencollective.com/lint-staged" - }, - "optionalDependencies": { - "yaml": "^2.8.4" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/lint-staged/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/listr2": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", - "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", - "dev": true, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz", + "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", "license": "MIT", "dependencies": { - "cli-truncate": "^5.2.0", - "eventemitter3": "^5.0.4", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^10.0.0" + "micromark-util-types": "^1.0.0" }, - "engines": { - "node": ">=22.13.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/local-pkg": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", - "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", + "node_modules/micromark-extension-gfm-tagfilter/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz", + "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", "license": "MIT", "dependencies": { - "mlly": "^1.7.4", - "pkg-types": "^2.3.0", - "quansync": "^0.2.11" - }, - "engines": { - "node": ">=14" + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "dev": true, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/lodash-es": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", - "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT" }, - "node_modules/lodash.isequal": { - "version": "4.5.0", + "node_modules/micromark-extension-gfm/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT" }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "dev": true, + "node_modules/micromark-factory-destination": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", + "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, + "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", - "dev": true, + "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-label": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", + "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, + "node_modules/micromark-factory-label/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "license": "ISC", + "node_modules/micromark-factory-space/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", "dependencies": { - "yallist": "^3.0.2" + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "3.1.1", - "license": "ISC" + "node_modules/micromark-factory-space/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/lucide-vue-next": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-1.0.0.tgz", - "integrity": "sha512-V6SPvx1IHTj/UY+FrIYWV5faISsPSb8BnWSFDxAtezWKvWc9ZZ40PDrdu1/Qb5vg4lHWr1hs1BAMGVGm6V1Xdg==", - "deprecated": "Package deprecated. Please use @lucide/vue instead.", - "license": "ISC", - "peerDependencies": { - "vue": ">=3.0.1" - } + "node_modules/micromark-factory-space/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/magic-string": { - "version": "0.30.21", + "node_modules/micromark-factory-title": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", + "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/magic-string-ast": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/magic-string-ast/-/magic-string-ast-1.0.3.tgz", - "integrity": "sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==", + "node_modules/micromark-factory-title/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "magic-string": "^0.30.19" - }, - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/maplibre-gl": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-2.4.0.tgz", - "integrity": "sha512-csNFylzntPmHWidczfgCZpvbTSmhaWvLRj9e1ezUDBEPizGgshgm3ea1T5TCNEEBq0roauu7BPuRZjA3wO4KqA==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@mapbox/geojson-rewind": "^0.5.2", - "@mapbox/jsonlint-lines-primitives": "^2.0.2", - "@mapbox/mapbox-gl-supported": "^2.0.1", - "@mapbox/point-geometry": "^0.1.0", - "@mapbox/tiny-sdf": "^2.0.5", - "@mapbox/unitbezier": "^0.0.1", - "@mapbox/vector-tile": "^1.3.1", - "@mapbox/whoots-js": "^3.1.0", - "@types/geojson": "^7946.0.10", - "@types/mapbox__point-geometry": "^0.1.2", - "@types/mapbox__vector-tile": "^1.3.0", - "@types/pbf": "^3.0.2", - "csscolorparser": "~1.0.3", - "earcut": "^2.2.4", - "geojson-vt": "^3.2.1", - "gl-matrix": "^3.4.3", - "global-prefix": "^3.0.0", - "murmurhash-js": "^1.0.0", - "pbf": "^3.2.1", - "potpack": "^1.0.2", - "quickselect": "^2.0.0", - "supercluster": "^7.1.5", - "tinyqueue": "^2.0.3", - "vt-pbf": "^3.1.3" - } + "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/mark.js": { - "version": "8.11.1", - "dev": true, + "node_modules/micromark-factory-title/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT" }, - "node_modules/math-intrinsics": { + "node_modules/micromark-factory-whitespace": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", + "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", - "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", - "dev": true, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-to-hast/node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "dev": true, + "node_modules/micromark-util-chunked": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", "funding": [ { "type": "GitHub Sponsors", @@ -9556,15 +9317,13 @@ ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "micromark-util-symbol": "^1.0.0" } }, - "node_modules/mdast-util-to-hast/node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "dev": true, + "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", "funding": [ { "type": "GitHub Sponsors", @@ -9577,11 +9336,10 @@ ], "license": "MIT" }, - "node_modules/mdast-util-to-hast/node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "dev": true, + "node_modules/micromark-util-classify-character": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", "funding": [ { "type": "GitHub Sponsors", @@ -9594,16 +9352,15 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" } }, - "node_modules/mdast-util-to-hast/node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "dev": true, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", "funding": [ { "type": "GitHub Sponsors", @@ -9614,13 +9371,16 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } }, - "node_modules/mdast-util-to-hast/node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "dev": true, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", "funding": [ { "type": "GitHub Sponsors", @@ -9633,23 +9393,10 @@ ], "license": "MIT" }, - "node_modules/memorystream": { - "version": "0.3.1", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "3.2.0", + "node_modules/micromark-util-classify-character/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", "funding": [ { "type": "GitHub Sponsors", @@ -9660,29 +9407,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "micromark-core-commonmark": "^1.0.1", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } + "license": "MIT" }, - "node_modules/micromark-core-commonmark": { + "node_modules/micromark-util-combine-extensions": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", + "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", "funding": [ { "type": "GitHub Sponsors", @@ -9694,134 +9424,15 @@ } ], "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "2.0.3", - "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^1.0.0", - "micromark-extension-gfm-footnote": "^1.0.0", - "micromark-extension-gfm-strikethrough": "^1.0.0", - "micromark-extension-gfm-table": "^1.0.0", - "micromark-extension-gfm-tagfilter": "^1.0.0", - "micromark-extension-gfm-task-list-item": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "1.1.2", - "license": "MIT", - "dependencies": { - "micromark-core-commonmark": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "1.0.7", - "license": "MIT", "dependencies": { "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "1.0.7", - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-factory-destination": { + "node_modules/micromark-util-combine-extensions/node_modules/micromark-util-types": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", "funding": [ { "type": "GitHub Sponsors", @@ -9832,15 +9443,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } + "license": "MIT" }, - "node_modules/micromark-factory-label": { + "node_modules/micromark-util-decode-numeric-character-reference": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", + "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", "funding": [ { "type": "GitHub Sponsors", @@ -9853,14 +9461,46 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "micromark-util-symbol": "^1.0.0" } }, - "node_modules/micromark-factory-space": { + "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", + "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", "funding": [ { "type": "GitHub Sponsors", @@ -9871,14 +9511,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" - } + "license": "MIT" }, - "node_modules/micromark-factory-title": { + "node_modules/micromark-util-normalize-identifier": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", + "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", "funding": [ { "type": "GitHub Sponsors", @@ -9891,14 +9529,13 @@ ], "license": "MIT", "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-symbol": "^1.0.0" } }, - "node_modules/micromark-factory-whitespace": { + "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", "funding": [ { "type": "GitHub Sponsors", @@ -9909,16 +9546,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } + "license": "MIT" }, - "node_modules/micromark-util-character": { - "version": "1.2.0", + "node_modules/micromark-util-resolve-all": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", "funding": [ { "type": "GitHub Sponsors", @@ -9931,12 +9564,13 @@ ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, - "node_modules/micromark-util-chunked": { + "node_modules/micromark-util-resolve-all/node_modules/micromark-util-types": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", "funding": [ { "type": "GitHub Sponsors", @@ -9947,13 +9581,13 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } + "license": "MIT" }, - "node_modules/micromark-util-classify-character": { - "version": "1.1.0", + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -9966,13 +9600,15 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-util-combine-extensions": { + "node_modules/micromark-util-subtokenize": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", + "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", "funding": [ { "type": "GitHub Sponsors", @@ -9986,11 +9622,15 @@ "license": "MIT", "dependencies": { "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" } }, - "node_modules/micromark-util-decode-numeric-character-reference": { + "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", "funding": [ { "type": "GitHub Sponsors", @@ -10001,13 +9641,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } + "license": "MIT" }, - "node_modules/micromark-util-encode": { + "node_modules/micromark-util-subtokenize/node_modules/micromark-util-types": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", "funding": [ { "type": "GitHub Sponsors", @@ -10020,8 +9659,11 @@ ], "license": "MIT" }, - "node_modules/micromark-util-html-tag-name": { - "version": "1.2.0", + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -10034,8 +9676,11 @@ ], "license": "MIT" }, - "node_modules/micromark-util-normalize-identifier": { - "version": "1.1.0", + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -10046,13 +9691,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } + "license": "MIT" }, - "node_modules/micromark-util-resolve-all": { - "version": "1.1.0", + "node_modules/micromark/node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", "funding": [ { "type": "GitHub Sponsors", @@ -10065,11 +9709,14 @@ ], "license": "MIT", "dependencies": { + "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, - "node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", + "node_modules/micromark/node_modules/micromark-util-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", "funding": [ { "type": "GitHub Sponsors", @@ -10080,15 +9727,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } + "license": "MIT" }, - "node_modules/micromark-util-subtokenize": { - "version": "1.1.0", + "node_modules/micromark/node_modules/micromark-util-sanitize-uri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", "funding": [ { "type": "GitHub Sponsors", @@ -10101,14 +9745,15 @@ ], "license": "MIT", "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" } }, - "node_modules/micromark-util-symbol": { + "node_modules/micromark/node_modules/micromark-util-symbol": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", "funding": [ { "type": "GitHub Sponsors", @@ -10121,8 +9766,10 @@ ], "license": "MIT" }, - "node_modules/micromark-util-types": { + "node_modules/micromark/node_modules/micromark-util-types": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", "funding": [ { "type": "GitHub Sponsors", @@ -10137,6 +9784,8 @@ }, "node_modules/micromatch": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -10147,6 +9796,19 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -10168,19 +9830,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mini-svg-data-uri": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", @@ -10191,16 +9840,16 @@ } }, "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.2" + "brace-expansion": "^5.0.5" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -10208,32 +9857,40 @@ }, "node_modules/minimist": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "7.1.2", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/minisearch": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", "dev": true, "license": "MIT" }, "node_modules/mitt": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "license": "MIT" }, "node_modules/mlly": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.1.tgz", - "integrity": "sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", "license": "MIT", "dependencies": { "acorn": "^8.16.0", @@ -10259,8 +9916,20 @@ "pathe": "^2.0.1" } }, + "node_modules/modern-tar": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.7.tgz", + "integrity": "sha512-t9VmxaqrmANnEOBhpSDI6HD192Ge48k8vmWqQQL7hSFEqHEYwZbbsu49+aKLWZeRvFs3j1pMhXOqqF4kPlvjkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/mri": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "license": "MIT", "engines": { "node": ">=4" @@ -10278,10 +9947,14 @@ }, "node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/muggle-string": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", "license": "MIT" }, "node_modules/murmurhash-js": { @@ -10292,9 +9965,9 @@ "peer": true }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", "funding": [ { "type": "github", @@ -10311,19 +9984,30 @@ }, "node_modules/natural-compare": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/neo-async": { "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.19", - "license": "MIT" + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/nopt": { "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", "dev": true, "license": "ISC", "dependencies": { @@ -10336,8 +10020,16 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/nostics": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/nostics/-/nostics-1.2.0.tgz", + "integrity": "sha512-FGqEfhQjrvo1lL8KFifdTQiNwwQHJxC1jtYE1Rc54qF/jxONUNL+kC9gS1krX8Q65PgrQ5fCqH/I4NhWBvdSqg==", + "license": "MIT" + }, "node_modules/npm-normalize-package-bin": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, "license": "ISC", "engines": { @@ -10371,40 +10063,14 @@ "npm": ">= 10" } }, - "node_modules/npm-run-all2/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/npm-run-all2/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/npm-run-all2/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", + "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=18" } }, "node_modules/npm-run-all2/node_modules/which": { @@ -10425,6 +10091,8 @@ }, "node_modules/nth-check": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10436,6 +10104,8 @@ }, "node_modules/object-inspect": { "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -10445,77 +10115,60 @@ } }, "node_modules/obug": { - "version": "2.1.1", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } }, "node_modules/ohash": { "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", "license": "MIT" }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/oniguruma-parser": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", - "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", "dev": true, "license": "MIT" }, "node_modules/oniguruma-to-es": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.5.tgz", - "integrity": "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", "dev": true, "license": "MIT", "dependencies": { - "oniguruma-parser": "^0.12.1", + "oniguruma-parser": "^0.12.2", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "node_modules/open": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", - "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", + "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", "dev": true, "license": "MIT", "dependencies": { - "default-browser": "^5.2.1", + "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", + "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", - "wsl-utils": "^0.1.0" + "powershell-utils": "^0.1.0", + "wsl-utils": "^0.3.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10523,6 +10176,8 @@ }, "node_modules/openapi-types": { "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", "license": "MIT" }, "node_modules/openapi-zod-client": { @@ -10585,42 +10240,6 @@ "openapi-types": ">=7" } }, - "node_modules/openapi-zod-client/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/openapi-zod-client/node_modules/ajv-draft-04": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", - "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", - "license": "MIT", - "peerDependencies": { - "ajv": "^8.5.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/openapi-zod-client/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, "node_modules/openapi-zod-client/node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -10638,6 +10257,8 @@ }, "node_modules/openapi3-ts": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-3.1.0.tgz", + "integrity": "sha512-1qKTvCCVoV0rkwUh1zq5o8QyghmwYPuhdvtjv1rFjuOnJToXhQyF8eGjNETQ8QmGjr9Jz/tkAKLITIl2s7dw3A==", "license": "MIT", "dependencies": { "yaml": "^2.1.3" @@ -10645,6 +10266,8 @@ }, "node_modules/optionator": { "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { @@ -10661,6 +10284,8 @@ }, "node_modules/p-limit": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10675,6 +10300,8 @@ }, "node_modules/p-locate": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { @@ -10689,16 +10316,23 @@ }, "node_modules/package-json-from-dist": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/parchment": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz", + "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==", "license": "BSD-3-Clause" }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "license": "MIT", + "peer": true, "dependencies": { "callsites": "^3.0.0" }, @@ -10708,7 +10342,10 @@ }, "node_modules/parse-json": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -10716,25 +10353,16 @@ "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-json/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "license": "MIT" - }, - "node_modules/parse-unit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz", - "integrity": "sha512-hrqldJHokR3Qj88EIlV/kAyAi/G5R2+R56TBANxNMy0uPlYcttx0jnMW6Yx5KsKPSbC3KddM/7qQm3+0wEXKxg==", - "license": "MIT", - "peer": true + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/pastable": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/pastable/-/pastable-2.2.1.tgz", + "integrity": "sha512-K4ClMxRKpgN4sXj6VIPPrvor/TMp2yPNCGtfhvV106C73SwefQ3FuegURsH7AQHpqu0WwbvKXRl1HQxF6qax9w==", "dependencies": { "@babel/core": "^7.20.12", "ts-toolbelt": "^9.6.0", @@ -10758,6 +10386,8 @@ }, "node_modules/pastable/node_modules/type-fest": { "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=14.16" @@ -10775,6 +10405,8 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { @@ -10783,6 +10415,8 @@ }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { @@ -10798,6 +10432,8 @@ }, "node_modules/path-scurry": { "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -10813,6 +10449,8 @@ }, "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, "license": "ISC" }, @@ -10828,6 +10466,8 @@ }, "node_modules/pathe": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "license": "MIT" }, "node_modules/pbf": { @@ -10852,27 +10492,32 @@ }, "node_modules/perfect-debounce": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pidtree": { - "version": "0.6.0", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.1.tgz", + "integrity": "sha512-e0F9AOF1JMrCfBsyJOwU9lNvQ0WtXTq0j/4jk0BQ5JSI9VAybPXmDpPRw/2FQ3e5d3ZFN1mLh7jW99m/jjaptw==", "dev": true, "license": "MIT", "bin": { @@ -10904,52 +10549,52 @@ } }, "node_modules/pkg-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", - "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.1.tgz", + "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==", "license": "MIT", "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", + "confbox": "^0.2.4", + "exsolve": "^1.0.8", "pathe": "^2.0.3" } }, "node_modules/playwright": { - "version": "1.60.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", - "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", + "version": "1.62.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.0.tgz", + "integrity": "sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.60.0" + "playwright-core": "1.62.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.60.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", - "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", + "version": "1.62.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.0.tgz", + "integrity": "sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/postcss": { - "version": "8.5.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", - "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", "funding": [ { "type": "opencollective", @@ -10966,7 +10611,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -10975,10 +10620,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", - "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", - "dev": true, + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -10995,8 +10639,23 @@ "license": "ISC", "peer": true }, + "node_modules/powershell-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { @@ -11020,7 +10679,9 @@ } }, "node_modules/prettier-linter-helpers": { - "version": "1.0.0", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, "license": "MIT", "dependencies": { @@ -11030,20 +10691,10 @@ "node": ">=6.0.0" } }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", "dev": true, "license": "MIT", "funding": { @@ -11053,6 +10704,8 @@ }, "node_modules/proto-list": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "dev": true, "license": "ISC" }, @@ -11063,15 +10716,13 @@ "license": "MIT", "peer": true }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "dev": true, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "engines": { + "node": ">=10" } }, "node_modules/punycode": { @@ -11085,18 +10736,18 @@ } }, "node_modules/puppeteer": { - "version": "25.0.2", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.0.2.tgz", - "integrity": "sha512-cXj/5RlDCzSC7k1YdBIm6prb8lK8lEdmScVbcalX1rBn4fqNN1UNuEz/HZZYiDLsK8dOGvyLpGjh6CgxCyqKtg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.3.0.tgz", + "integrity": "sha512-O1tx8S315aw8eI99HZ5ZNcVEzJ9+jKF//eO5UvfZ3cXJ6okZ5sX3Y50u7DJaM+ewEK4LqXP068tBhfRaWikj+g==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "3.0.2", + "@puppeteer/browsers": "3.0.6", "chromium-bidi": "16.0.1", - "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1608973", - "puppeteer-core": "25.0.2", + "devtools-protocol": "0.0.1638949", + "lilconfig": "^3.1.3", + "puppeteer-core": "25.3.0", "typed-query-selector": "^2.12.2" }, "bin": { @@ -11107,58 +10758,31 @@ } }, "node_modules/puppeteer-core": { - "version": "25.0.2", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.0.2.tgz", - "integrity": "sha512-Q0IUIHER1S9PiNIfdNFc+pVOj79Tp4b9v0Fv4enigwsLy0Hbgq45KFgqzmN31DeCXh+Uvxnt9r7fMERhAMjs8Q==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.3.0.tgz", + "integrity": "sha512-fm+wpUr2oigH1PXZvwgATrM2tYWHMDG8ASzTEe9uukCye4X5Ldx1K5BTHPFKITrIWvQQAQ256d1NpbEveBcKjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "3.0.2", + "@puppeteer/browsers": "3.0.6", "chromium-bidi": "16.0.1", - "debug": "^4.4.3", - "devtools-protocol": "0.0.1608973", + "devtools-protocol": "0.0.1638949", "typed-query-selector": "^2.12.2", - "webdriver-bidi-protocol": "0.4.1", - "ws": "^8.20.0" + "webdriver-bidi-protocol": "0.4.2", + "ws": "^8.21.0" }, "engines": { "node": ">=22.12.0" } }, - "node_modules/puppeteer/node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/qs": { - "version": "6.15.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", - "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" }, "engines": { "node": ">=0.6" @@ -11185,6 +10809,8 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -11226,6 +10852,8 @@ }, "node_modules/quill-delta": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", "license": "MIT", "dependencies": { "fast-diff": "^1.3.0", @@ -11244,6 +10872,8 @@ }, "node_modules/read-package-json-fast": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", + "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", "dev": true, "license": "ISC", "dependencies": { @@ -11254,6 +10884,16 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/readdirp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", @@ -11295,9 +10935,9 @@ "license": "MIT" }, "node_modules/reka-ui": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.8.2.tgz", - "integrity": "sha512-8lTKcJhmG+D3UyJxhBnNnW/720sLzm0pbA9AC1MWazmJ5YchJAyTSl+O00xP/kxBmEN0fw5JqWVHguiFmsGjzA==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.10.1.tgz", + "integrity": "sha512-drcOQ4rQtDYAcGCsyQBqQg8QQ+H3B+zDaMJU0h8KPEPMa7g9BHu3zcOi4OB39XJSWizceFoNO0Z9tctSGLOXqg==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.6.13", @@ -11308,7 +10948,7 @@ "@vueuse/core": "^14.1.0", "@vueuse/shared": "^14.1.0", "aria-hidden": "^1.2.4", - "defu": "^6.1.4", + "defu": "^6.1.5", "ohash": "^2.0.11" }, "funding": { @@ -11316,47 +10956,13 @@ "url": "https://github.com/sponsors/zernonia" }, "peerDependencies": { - "vue": ">= 3.2.0" - } - }, - "node_modules/reka-ui/node_modules/@vueuse/core": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.1.tgz", - "integrity": "sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==", - "license": "MIT", - "dependencies": { - "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "14.2.1", - "@vueuse/shared": "14.2.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/reka-ui/node_modules/@vueuse/metadata": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.2.1.tgz", - "integrity": "sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "vue": ">= 3.4.0" } }, "node_modules/require-from-string": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11386,19 +10992,14 @@ }, "node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "license": "MIT", + "peer": true, "engines": { "node": ">=4" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "devOptional": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, "node_modules/resolve-protobuf-schema": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", @@ -11409,25 +11010,10 @@ "protocol-buffers-schema": "^3.3.1" } }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/reusify": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -11437,6 +11023,8 @@ }, "node_modules/rfdc": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, "node_modules/robust-predicates": { @@ -11447,12 +11035,12 @@ "peer": true }, "node_modules/rolldown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.4.tgz", - "integrity": "sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", + "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.138.0", + "@oxc-project/types": "=0.139.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -11462,31 +11050,31 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.1.4", - "@rolldown/binding-darwin-arm64": "1.1.4", - "@rolldown/binding-darwin-x64": "1.1.4", - "@rolldown/binding-freebsd-x64": "1.1.4", - "@rolldown/binding-linux-arm-gnueabihf": "1.1.4", - "@rolldown/binding-linux-arm64-gnu": "1.1.4", - "@rolldown/binding-linux-arm64-musl": "1.1.4", - "@rolldown/binding-linux-ppc64-gnu": "1.1.4", - "@rolldown/binding-linux-s390x-gnu": "1.1.4", - "@rolldown/binding-linux-x64-gnu": "1.1.4", - "@rolldown/binding-linux-x64-musl": "1.1.4", - "@rolldown/binding-openharmony-arm64": "1.1.4", - "@rolldown/binding-wasm32-wasi": "1.1.4", - "@rolldown/binding-win32-arm64-msvc": "1.1.4", - "@rolldown/binding-win32-x64-msvc": "1.1.4" + "@rolldown/binding-android-arm64": "1.1.5", + "@rolldown/binding-darwin-arm64": "1.1.5", + "@rolldown/binding-darwin-x64": "1.1.5", + "@rolldown/binding-freebsd-x64": "1.1.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", + "@rolldown/binding-linux-arm64-gnu": "1.1.5", + "@rolldown/binding-linux-arm64-musl": "1.1.5", + "@rolldown/binding-linux-ppc64-gnu": "1.1.5", + "@rolldown/binding-linux-s390x-gnu": "1.1.5", + "@rolldown/binding-linux-x64-gnu": "1.1.5", + "@rolldown/binding-linux-x64-musl": "1.1.5", + "@rolldown/binding-openharmony-arm64": "1.1.5", + "@rolldown/binding-wasm32-wasi": "1.1.5", + "@rolldown/binding-win32-arm64-msvc": "1.1.5", + "@rolldown/binding-win32-x64-msvc": "1.1.5" } }, "node_modules/rollup": { - "version": "4.60.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", - "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", - "dev": true, + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.3.tgz", + "integrity": "sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==", + "devOptional": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@types/estree": "1.0.9" }, "bin": { "rollup": "dist/bin/rollup" @@ -11496,74 +11084,74 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.2", - "@rollup/rollup-android-arm64": "4.60.2", - "@rollup/rollup-darwin-arm64": "4.60.2", - "@rollup/rollup-darwin-x64": "4.60.2", - "@rollup/rollup-freebsd-arm64": "4.60.2", - "@rollup/rollup-freebsd-x64": "4.60.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", - "@rollup/rollup-linux-arm-musleabihf": "4.60.2", - "@rollup/rollup-linux-arm64-gnu": "4.60.2", - "@rollup/rollup-linux-arm64-musl": "4.60.2", - "@rollup/rollup-linux-loong64-gnu": "4.60.2", - "@rollup/rollup-linux-loong64-musl": "4.60.2", - "@rollup/rollup-linux-ppc64-gnu": "4.60.2", - "@rollup/rollup-linux-ppc64-musl": "4.60.2", - "@rollup/rollup-linux-riscv64-gnu": "4.60.2", - "@rollup/rollup-linux-riscv64-musl": "4.60.2", - "@rollup/rollup-linux-s390x-gnu": "4.60.2", - "@rollup/rollup-linux-x64-gnu": "4.60.2", - "@rollup/rollup-linux-x64-musl": "4.60.2", - "@rollup/rollup-openbsd-x64": "4.60.2", - "@rollup/rollup-openharmony-arm64": "4.60.2", - "@rollup/rollup-win32-arm64-msvc": "4.60.2", - "@rollup/rollup-win32-ia32-msvc": "4.60.2", - "@rollup/rollup-win32-x64-gnu": "4.60.2", - "@rollup/rollup-win32-x64-msvc": "4.60.2", + "@rollup/rollup-android-arm-eabi": "4.62.3", + "@rollup/rollup-android-arm64": "4.62.3", + "@rollup/rollup-darwin-arm64": "4.62.3", + "@rollup/rollup-darwin-x64": "4.62.3", + "@rollup/rollup-freebsd-arm64": "4.62.3", + "@rollup/rollup-freebsd-x64": "4.62.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.3", + "@rollup/rollup-linux-arm-musleabihf": "4.62.3", + "@rollup/rollup-linux-arm64-gnu": "4.62.3", + "@rollup/rollup-linux-arm64-musl": "4.62.3", + "@rollup/rollup-linux-loong64-gnu": "4.62.3", + "@rollup/rollup-linux-loong64-musl": "4.62.3", + "@rollup/rollup-linux-ppc64-gnu": "4.62.3", + "@rollup/rollup-linux-ppc64-musl": "4.62.3", + "@rollup/rollup-linux-riscv64-gnu": "4.62.3", + "@rollup/rollup-linux-riscv64-musl": "4.62.3", + "@rollup/rollup-linux-s390x-gnu": "4.62.3", + "@rollup/rollup-linux-x64-gnu": "4.62.3", + "@rollup/rollup-linux-x64-musl": "4.62.3", + "@rollup/rollup-openbsd-x64": "4.62.3", + "@rollup/rollup-openharmony-arm64": "4.62.3", + "@rollup/rollup-win32-arm64-msvc": "4.62.3", + "@rollup/rollup-win32-ia32-msvc": "4.62.3", + "@rollup/rollup-win32-x64-gnu": "4.62.3", + "@rollup/rollup-win32-x64-msvc": "4.62.3", "fsevents": "~2.3.2" } }, "node_modules/rrdom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rrdom/-/rrdom-2.1.0.tgz", - "integrity": "sha512-d7oaIHzwffxI74UJMZDGq/f97/Yfm3QX4CcTIlQelt2HsLavItLjp8x8nQ0g9Pet5+5wG1RGr9yvsxb1gJlo8A==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/rrdom/-/rrdom-2.1.1.tgz", + "integrity": "sha512-VBkTF3bGNqcZjqnbo/gKi9GVQPIxiG0dofw7CQdAZQFQ2juJdt2YKIf3oS9QudL8HTpGh9bz5TUN+3amBn1Geg==", "license": "MIT", "dependencies": { - "rrweb-snapshot": "^2.1.0" + "rrweb-snapshot": "^2.1.1" } }, "node_modules/rrweb": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rrweb/-/rrweb-2.1.0.tgz", - "integrity": "sha512-gGGvd1eXWnOuJpQumH7+gPmBwTXzNrjmQyedWVePcEx0S5fe3VkQW4vw5f5ItY+vuigaaktte9cZKOg0OEvv+w==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/rrweb/-/rrweb-2.1.1.tgz", + "integrity": "sha512-ToxhJg3SsrAhw+/DPhI/2iiwZQIrGK5BGkZ0kHn4qUExcvQYRaolkciD1FWX2+r6vf1IxFyhsoRY18h3D+XoCg==", "license": "MIT", "dependencies": { - "@rrweb/types": "^2.1.0", - "@rrweb/utils": "^2.1.0", + "@rrweb/types": "^2.1.1", + "@rrweb/utils": "^2.1.1", "@types/css-font-loading-module": "0.0.7", "@xstate/fsm": "^1.4.0", "base64-arraybuffer": "^1.0.1", "mitt": "^3.0.0", - "rrdom": "^2.1.0", - "rrweb-snapshot": "^2.1.0" + "rrdom": "^2.1.1", + "rrweb-snapshot": "^2.1.1" } }, "node_modules/rrweb-player": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rrweb-player/-/rrweb-player-2.1.0.tgz", - "integrity": "sha512-EU0dCgrN66o2E8GAT67wDBRMgcJ1QJuu2lGa8PKO3xSosSS2eCaHlJWmX9fFCMvKkLsahWe15GnuqUjprCGMoA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/rrweb-player/-/rrweb-player-2.1.1.tgz", + "integrity": "sha512-oiAWx/m9Pz0DD5jlJdrF8QlotOZZBK0jINNSYAixxhGa2dI1TrzVVmF4eWFSd6AR8f2zjazKXI/PXCqj3PttXQ==", "license": "MIT", "dependencies": { - "@rrweb/packer": "^2.1.0", - "@rrweb/replay": "^2.1.0", + "@rrweb/packer": "^2.1.1", + "@rrweb/replay": "^2.1.1", "@tsconfig/svelte": "^1.0.0" } }, "node_modules/rrweb-snapshot": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rrweb-snapshot/-/rrweb-snapshot-2.1.0.tgz", - "integrity": "sha512-CFjUKWlO+Dl72gk8qwcDcNE/Pj9yr6IvGRAiRAx12pmJaSWaOKFoFgpQQ1j/mW0WKwEZXbHnMJL8M92gIsdwUQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/rrweb-snapshot/-/rrweb-snapshot-2.1.1.tgz", + "integrity": "sha512-al4Kx7Am7YlIn/5Yb2EMr7cdmjGiK+cLhdilJEXqkFXgpnys8t/yMJumXy2Ormgirpg3MBnFha0GTgny+iIL2w==", "license": "MIT", "dependencies": { "postcss": "^8.4.38" @@ -11584,6 +11172,8 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -11613,6 +11203,8 @@ }, "node_modules/sade": { "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", "license": "MIT", "dependencies": { "mri": "^1.1.0" @@ -11635,9 +11227,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { @@ -11649,6 +11241,8 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { @@ -11660,6 +11254,8 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { @@ -11667,9 +11263,9 @@ } }, "node_modules/shell-quote": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", - "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", + "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", "dev": true, "license": "MIT", "engines": { @@ -11697,12 +11293,14 @@ } }, "node_modules/side-channel": { - "version": "1.1.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, @@ -11714,11 +11312,13 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -11729,6 +11329,8 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -11745,6 +11347,8 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -11762,11 +11366,15 @@ }, "node_modules/siginfo": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/signal-exit": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", "engines": { @@ -11791,51 +11399,26 @@ "node": ">=18" } }, - "node_modules/slice-ansi": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", - "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.3", - "is-fullwidth-code-point": "^5.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/sortablejs": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz", - "integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.7.tgz", + "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==", "license": "MIT" }, "node_modules/source-map": { - "version": "0.6.1", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "license": "BSD-3-Clause", + "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-js": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -11854,6 +11437,8 @@ }, "node_modules/speakingurl": { "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -11861,30 +11446,22 @@ }, "node_modules/stackback": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/std-env": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", - "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", "dev": true, "license": "MIT" }, - "node_modules/streamx": { - "version": "2.25.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", - "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", - "dev": true, - "license": "MIT", - "dependencies": { - "events-universal": "^1.0.0", - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" - } - }, "node_modules/string-argv": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, "license": "MIT", "engines": { @@ -11892,17 +11469,18 @@ } }, "node_modules/string-width": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", - "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", "dependencies": { - "get-east-asian-width": "^1.5.0", - "strip-ansi": "^7.1.2" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=20" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11911,6 +11489,8 @@ "node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -11924,6 +11504,8 @@ }, "node_modules/string-width-cjs/node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { @@ -11932,19 +11514,15 @@ }, "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -11988,6 +11566,8 @@ "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -11999,6 +11579,8 @@ }, "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { @@ -12030,10 +11612,12 @@ } }, "node_modules/superjson": { - "version": "2.2.2", + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", "license": "MIT", "dependencies": { - "copy-anything": "^3.0.2" + "copy-anything": "^4" }, "engines": { "node": ">=16" @@ -12053,11 +11637,13 @@ } }, "node_modules/synckit": { - "version": "0.11.8", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.4" + "@pkgr/core": "^0.3.6" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -12067,9 +11653,9 @@ } }, "node_modules/tabbable": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", - "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.5.0.tgz", + "integrity": "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==", "dev": true, "license": "MIT" }, @@ -12084,13 +11670,15 @@ } }, "node_modules/tailwindcss": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.2.tgz", - "integrity": "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", "license": "MIT" }, "node_modules/tanu": { "version": "0.1.13", + "resolved": "https://registry.npmjs.org/tanu/-/tanu-0.1.13.tgz", + "integrity": "sha512-UbRmX7ccZ4wMVOY/Uw+7ji4VOkEYSYJG1+I4qzbnn4qh/jtvVbrm6BFnF12NQQ4+jGv21wKmjb1iFyUSVnBWcQ==", "license": "MIT", "dependencies": { "tslib": "^2.4.0", @@ -12099,6 +11687,8 @@ }, "node_modules/tanu/node_modules/typescript": { "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -12121,54 +11711,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/tar-fs": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.2.tgz", - "integrity": "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0" - } - }, - "node_modules/tar-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz", - "integrity": "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "bare-fs": "^4.5.5", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "node_modules/teex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", - "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "streamx": "^2.12.5" - } - }, - "node_modules/text-decoder": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", - "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } - }, "node_modules/three": { "version": "0.135.0", "resolved": "https://registry.npmjs.org/three/-/three-0.135.0.tgz", @@ -12188,13 +11730,15 @@ }, "node_modules/tinybench": { "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.2.tgz", - "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", "engines": { @@ -12211,37 +11755,10 @@ "picomatch": "^4.0.4" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "license": "MIT", - "engines": { - "node": ">=12" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyqueue": { @@ -12261,18 +11778,10 @@ "node": ">=14.0.0" } }, - "node_modules/to-px": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/to-px/-/to-px-1.1.0.tgz", - "integrity": "sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw==", - "license": "MIT", - "peer": true, - "dependencies": { - "parse-unit": "^1.0.1" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12339,26 +11848,31 @@ } }, "node_modules/ts-pattern": { - "version": "5.7.1", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.9.0.tgz", + "integrity": "sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==", "license": "MIT" }, "node_modules/ts-toolbelt": { "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", "license": "Apache-2.0" }, "node_modules/tslib": { "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz", + "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==", "devOptional": true, "license": "MIT", "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" + "esbuild": "~0.28.0" }, "bin": { "tsx": "dist/cli.mjs" @@ -12395,6 +11909,8 @@ }, "node_modules/type-check": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { @@ -12406,6 +11922,8 @@ }, "node_modules/type-fest": { "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" @@ -12421,880 +11939,686 @@ "dev": true, "license": "MIT" }, - "node_modules/typescript": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", - "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ufo": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", - "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/undici-types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", - "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", - "license": "MIT" - }, - "node_modules/unist-util-is": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", - "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unplugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-3.0.0.tgz", - "integrity": "sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==", - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "picomatch": "^4.0.3", - "webpack-virtual-modules": "^0.6.2" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/unplugin-utils": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.1.tgz", - "integrity": "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==", - "license": "MIT", - "dependencies": { - "pathe": "^2.0.3", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" - } - }, - "node_modules/unplugin-utils/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/unplugin/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/uuid": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", - "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist-node/bin/uuid" - } - }, - "node_modules/uvu": { - "version": "0.5.6", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/vaul-vue": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/vaul-vue/-/vaul-vue-0.4.1.tgz", - "integrity": "sha512-A6jOWOZX5yvyo1qMn7IveoWN91mJI5L3BUKsIwkg6qrTGgHs1Sb1JF/vyLJgnbN1rH4OOOxFbtqL9A46bOyGUQ==", - "dependencies": { - "@vueuse/core": "^10.8.0", - "reka-ui": "^2.0.0", - "vue": "^3.4.5" - }, - "peerDependencies": { - "reka-ui": "^2.0.0", - "vue": "^3.3.0" - } - }, - "node_modules/vaul-vue/node_modules/@types/web-bluetooth": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", - "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", - "license": "MIT" - }, - "node_modules/vaul-vue/node_modules/@vueuse/core": { - "version": "10.11.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz", - "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==", - "license": "MIT", - "dependencies": { - "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "10.11.1", - "@vueuse/shared": "10.11.1", - "vue-demi": ">=0.14.8" + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "engines": { + "node": ">=14.17" } }, - "node_modules/vaul-vue/node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, + "node_modules/typescript-eslint": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.65.0.tgz", + "integrity": "sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==", + "dev": true, "license": "MIT", - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.65.0", + "@typescript-eslint/parser": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/utils": "8.65.0" }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/vaul-vue/node_modules/@vueuse/metadata": { - "version": "10.11.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz", - "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" } }, - "node_modules/vaul-vue/node_modules/@vueuse/shared": { - "version": "10.11.1", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz", - "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==", + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "license": "MIT" + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, "license": "MIT", "dependencies": { - "vue-demi": ">=0.14.8" + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/antfu" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/vaul-vue/node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, "license": "MIT", - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" + "dependencies": { + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/vee-validate": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.15.1.tgz", - "integrity": "sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg==", + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-api": "^7.5.2", - "type-fest": "^4.8.3" + "@types/unist": "^3.0.0" }, - "peerDependencies": { - "vue": "^3.4.26" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "unist-util-is": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/vite": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz", - "integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unplugin": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-3.3.0.tgz", + "integrity": "sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==", "license": "MIT", "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.16", - "rolldown": "~1.1.4", - "tinyglobby": "^0.2.17" - }, - "bin": { - "vite": "bin/vite.js" + "@jridgewell/remapping": "^2.3.5", + "picomatch": "^4.0.4", + "webpack-virtual-modules": "^0.6.2" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.3.0", - "esbuild": "^0.27.0 || ^0.28.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" + "@farmfe/core": "*", + "@rspack/core": "*", + "bun-types-no-globals": "*", + "esbuild": "*", + "rolldown": "*", + "rollup": "*", + "unloader": "*", + "vite": "*", + "webpack": "*" }, "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "@vitejs/devtools": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jiti": { + "@farmfe/core": { "optional": true }, - "less": { + "@rspack/core": { "optional": true }, - "sass": { + "bun-types-no-globals": { "optional": true }, - "sass-embedded": { + "esbuild": { "optional": true }, - "stylus": { + "rolldown": { "optional": true }, - "sugarss": { + "rollup": { "optional": true }, - "terser": { + "unloader": { "optional": true }, - "tsx": { + "vite": { "optional": true }, - "yaml": { + "webpack": { "optional": true } } }, - "node_modules/vite-plugin-vue-devtools": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.1.5.tgz", - "integrity": "sha512-QSVntSN0sbVV08CZntMWOfF8McyPyYyYd19sChLjxYyFCC7Fcpey74ztw1uCCU23wTmR2yWPb92uaxVD4Lw0Fg==", - "dev": true, + "node_modules/unplugin-utils": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.2.tgz", + "integrity": "sha512-xVToRh2CTmLk2HnEG7ac4rl1MJTT3RFkpS8B++/SnB0kXvuaavD+n3m/vrzyWQOdJNSZQACnbz01pnppbwV5BA==", "license": "MIT", "dependencies": { - "@vue/devtools-core": "^8.1.5", - "@vue/devtools-kit": "^8.1.5", - "@vue/devtools-shared": "^8.1.5", - "sirv": "^3.0.2", - "vite-plugin-inspect": "^11.3.3", - "vite-plugin-vue-inspector": "^6.0.0" + "pathe": "^2.0.3", + "picomatch": "^4.0.4" }, "engines": { - "node": ">=v14.21.3" + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" }, "peerDependencies": { - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + "browserslist": ">= 4.21.0" } }, - "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-kit": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.1.5.tgz", - "integrity": "sha512-FcSAxsi4eWuXLCB7Rv9lj0aIVHHPNVQ2BazGf4RJTc2JCqb4BQg0hk87ZFhminCfl+mD5OUI0rX2cgyu4kJOGA==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@vue/devtools-shared": "^8.1.5", - "birpc": "^2.6.1", - "hookable": "^5.5.3", - "perfect-debounce": "^2.0.0" + "punycode": "^2.1.0" } }, - "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-shared": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.1.5.tgz", - "integrity": "sha512-mhT4zcPFhF+Xk1O4BfhhrbXzpmfqY03fS6xGpcllbQG7lDjhQf8pQHcTIhqQIYx1hfwtHmk/6jM96ele0UxPqQ==", - "dev": true, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/vite-plugin-vue-devtools/node_modules/perfect-debounce": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", - "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", - "dev": true, - "license": "MIT" + "node_modules/uuid": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } }, - "node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.3.3.tgz", - "integrity": "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==", - "dev": true, + "node_modules/uvu": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", "license": "MIT", "dependencies": { - "ansis": "^4.1.0", - "debug": "^4.4.1", - "error-stack-parser-es": "^1.0.5", - "ohash": "^2.0.11", - "open": "^10.2.0", - "perfect-debounce": "^2.0.0", - "sirv": "^3.0.1", - "unplugin-utils": "^0.3.0", - "vite-dev-rpc": "^1.1.0" + "dequal": "^2.0.0", + "diff": "^5.0.0", + "kleur": "^4.0.3", + "sade": "^1.7.3" }, - "engines": { - "node": ">=14" + "bin": { + "uvu": "bin.js" }, - "funding": { - "url": "https://github.com/sponsors/antfu" + "engines": { + "node": ">=8" + } + }, + "node_modules/vaul-vue": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/vaul-vue/-/vaul-vue-0.4.1.tgz", + "integrity": "sha512-A6jOWOZX5yvyo1qMn7IveoWN91mJI5L3BUKsIwkg6qrTGgHs1Sb1JF/vyLJgnbN1rH4OOOxFbtqL9A46bOyGUQ==", + "dependencies": { + "@vueuse/core": "^10.8.0", + "reka-ui": "^2.0.0", + "vue": "^3.4.5" }, "peerDependencies": { - "vite": "^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "@nuxt/kit": { - "optional": true - } + "reka-ui": "^2.0.0", + "vue": "^3.3.0" } }, - "node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect/node_modules/vite-dev-rpc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz", - "integrity": "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==", - "dev": true, + "node_modules/vaul-vue/node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "license": "MIT" + }, + "node_modules/vaul-vue/node_modules/@vueuse/core": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz", + "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==", "license": "MIT", "dependencies": { - "birpc": "^2.4.0", - "vite-hot-client": "^2.1.0" + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.11.1", + "@vueuse/shared": "10.11.1", + "vue-demi": ">=0.14.8" }, "funding": { "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0" } }, - "node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect/node_modules/vite-dev-rpc/node_modules/vite-hot-client": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.1.0.tgz", - "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", - "dev": true, + "node_modules/vaul-vue/node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, "funding": { "url": "https://github.com/sponsors/antfu" }, "peerDependencies": { - "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/vite-plugin-vue-inspector": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-6.0.0.tgz", - "integrity": "sha512-OpyITJLgZNibxlrik1EmRtvXHDjLRxNPsWkGFTERZs2LgMEdG4W0WoFt5GIgp3a3jRou+eJR8U1zOBk/XQgEbw==", - "dev": true, + "node_modules/vaul-vue/node_modules/@vueuse/metadata": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz", + "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/vaul-vue/node_modules/@vueuse/shared": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz", + "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==", "license": "MIT", "dependencies": { - "@babel/core": "^7.23.0", - "@babel/plugin-proposal-decorators": "^7.23.0", - "@babel/plugin-syntax-import-attributes": "^7.22.5", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-transform-typescript": "^7.22.15", - "@vue/babel-plugin-jsx": "^1.1.5", - "@vue/compiler-dom": "^3.3.4", - "kolorist": "^1.8.0", - "magic-string": "^0.30.4" + "vue-demi": ">=0.14.8" }, - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/vite/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/vaul-vue/node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", "hasInstallScript": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/vite/node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" }, "engines": { - "node": ">= 12.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/antfu" }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/vite/node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/vee-validate": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.15.1.tgz", + "integrity": "sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.5.2", + "type-fest": "^4.8.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "vue": "^3.4.26" } }, - "node_modules/vite/node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/unified" } }, - "node_modules/vite/node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/unified" } }, - "node_modules/vite/node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/vite": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", + "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.17", + "rolldown": "~1.1.5", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, "engines": { - "node": ">= 12.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.3.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/vite-dev-rpc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-2.0.0.tgz", + "integrity": "sha512-yKwbTwdHKSD2k/aGqyWpPHepo45OQc8lH3/6IfT4ZqeKE26ooKvi4WIEKzqWav8v+9Is8u1k8q54hvOmqASazA==", + "dev": true, + "license": "MIT", + "dependencies": { + "birpc": "^4.0.0", + "vite-hot-client": "^2.2.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0 || ^8.0.0" } }, - "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, + "node_modules/vite-dev-rpc/node_modules/birpc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz", + "integrity": "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==", + "dev": true, + "license": "MIT", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, + "node_modules/vite-hot-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.2.0.tgz", + "integrity": "sha512-76Zs9zrHbH7M7wqeyooGQKdX+yg0pQ0xuQ1PbFp4z5a0Lzn2e5IPFoCswnmqZ4GiwqB4Jo3WcDAMO9jARTJl8w==", + "dev": true, + "license": "MIT", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0" } }, - "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], + "node_modules/vite-plugin-inspect": { + "version": "11.4.1", + "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.4.1.tgz", + "integrity": "sha512-ShOFe2PURXGvRS5OrgmOLZOCwDTD7dEBVt0tMpFPKb9AsvqXKCRGM8QgKrUbRbJYFXScHvDPpGRd28rYidC0tA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansis": "^4.3.0", + "error-stack-parser-es": "^1.0.5", + "obug": "^2.1.1", + "ohash": "^2.0.11", + "open": "^11.0.0", + "perfect-debounce": "^2.1.0", + "sirv": "^3.0.2", + "unplugin-utils": "^0.3.1", + "vite-dev-rpc": "^2.0.0" + }, "engines": { - "node": ">= 12.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0-0 || ^8.0.0-0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } } }, - "node_modules/vite/node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], + "node_modules/vite-plugin-inspect/node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.2.1.tgz", + "integrity": "sha512-5JLxXWWCo5lJMw16/xVeNvJ8k2zLwZPf1vITLzya/2IePrCBeGe/p/iAokgXHZpEi39fcYtPXmO8SaKeXmqCAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-core": "^8.2.1", + "@vue/devtools-kit": "^8.2.1", + "@vue/devtools-shared": "^8.2.1", + "sirv": "^3.0.2", + "vite-plugin-inspect": "^11.3.3", + "vite-plugin-vue-inspector": "^6.0.0" + }, "engines": { - "node": ">= 12.0.0" + "node": ">=v14.21.3" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-kit": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", + "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.2.1", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "perfect-debounce": "^2.0.0" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-shared": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", + "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-devtools/node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-inspector": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-6.0.0.tgz", + "integrity": "sha512-OpyITJLgZNibxlrik1EmRtvXHDjLRxNPsWkGFTERZs2LgMEdG4W0WoFt5GIgp3a3jRou+eJR8U1zOBk/XQgEbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ - "win32" + "darwin" ], "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/vitepress": { @@ -13345,81 +12669,35 @@ } }, "node_modules/vitepress/node_modules/@vue/devtools-api": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.1.1.tgz", - "integrity": "sha512-bsDMJ07b3GN1puVwJb/fyFnj/U2imyswK5UQVLZwVl7O05jDrt6BHxeG5XffmOOdasOj/bOmIjxJvGPxU7pcqw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.2.1.tgz", + "integrity": "sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==", "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-kit": "^8.1.1" + "@vue/devtools-kit": "^8.2.1" } }, "node_modules/vitepress/node_modules/@vue/devtools-kit": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.1.1.tgz", - "integrity": "sha512-gVBaBv++i+adg4JpH71k9ppl4soyR7Y2McEqO5YNgv0BI1kMZ7BDX5gnwkZ5COYgiCyhejZG+yGNrBAjj6Coqg==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", + "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-shared": "^8.1.1", + "@vue/devtools-shared": "^8.2.1", "birpc": "^2.6.1", "hookable": "^5.5.3", "perfect-debounce": "^2.0.0" } }, "node_modules/vitepress/node_modules/@vue/devtools-shared": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.1.1.tgz", - "integrity": "sha512-+h4ttmJYl/txpxHKaoZcaKpC+pvckgLzIDiSQlaQ7kKthKh8KuwoLW2D8hPJEnqKzXOvu15UHEoGyngAXCz0EQ==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", + "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", "dev": true, "license": "MIT" }, - "node_modules/vitepress/node_modules/@vueuse/core": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.1.tgz", - "integrity": "sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/web-bluetooth": "^0.0.21", - "@vueuse/metadata": "14.2.1", - "@vueuse/shared": "14.2.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/vitepress/node_modules/@vueuse/metadata": { - "version": "14.2.1", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.2.1.tgz", - "integrity": "sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/vitepress/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, "node_modules/vitepress/node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -13442,27 +12720,14 @@ "dev": true, "license": "MIT" }, - "node_modules/vitepress/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/vitepress/node_modules/vite": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", - "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", @@ -13531,19 +12796,19 @@ } }, "node_modules/vitest": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.7.tgz", - "integrity": "sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.7", - "@vitest/mocker": "4.1.7", - "@vitest/pretty-format": "4.1.7", - "@vitest/runner": "4.1.7", - "@vitest/snapshot": "4.1.7", - "@vitest/spy": "4.1.7", - "@vitest/utils": "4.1.7", + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -13571,12 +12836,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.7", - "@vitest/browser-preview": "4.1.7", - "@vitest/browser-webdriverio": "4.1.7", - "@vitest/coverage-istanbul": "4.1.7", - "@vitest/coverage-v8": "4.1.7", - "@vitest/ui": "4.1.7", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -13620,19 +12885,6 @@ } } }, - "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/vscode-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", @@ -13653,16 +12905,16 @@ } }, "node_modules/vue": { - "version": "3.5.39", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.39.tgz", - "integrity": "sha512-xmZCYabFGcirU8r0fTuvl/LICc1OU620rnqepaJDL/a141ZigkG7AyaxQLdqJ02ZRYzWe6YPaDHeQx7MfknQfA==", + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.40.tgz", + "integrity": "sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.39", - "@vue/compiler-sfc": "3.5.39", - "@vue/runtime-dom": "3.5.39", - "@vue/server-renderer": "3.5.39", - "@vue/shared": "3.5.39" + "@vue/compiler-dom": "3.5.40", + "@vue/compiler-sfc": "3.5.40", + "@vue/runtime-dom": "3.5.40", + "@vue/server-renderer": "3.5.40", + "@vue/shared": "3.5.40" }, "peerDependencies": { "typescript": "*" @@ -13685,14 +12937,16 @@ } }, "node_modules/vue-component-type-helpers": { - "version": "2.2.12", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-3.3.8.tgz", + "integrity": "sha512-troqCMmQodQDqUqn63NQaFi+CDSclSe7sc8VEBFqf5GFLqmGR2Ph3P2WEC7qwpRVyEWsTi/aAr4vyOe/B1hU3g==", "dev": true, "license": "MIT" }, "node_modules/vue-eslint-parser": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.0.tgz", - "integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.1.tgz", + "integrity": "sha512-Gk6gRDj0n/fkRa3C3l0bBheoBckUq/Rs0F/TvMWIS6nzzx67amAViMe9CkNgsP2tXyQONvGiHQESHwFtZ3aYDA==", "dev": true, "license": "MIT", "dependencies": { @@ -13727,37 +12981,39 @@ } }, "node_modules/vue-router": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.0.7.tgz", - "integrity": "sha512-dqfk8kvRbCutmCOCj/XLDqDEYxc1wBdAOGLuVy5M93ifYMsBd5fIjfaPN4tQAbxr5IprdBDIox1gr4wYyOx/SA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.2.0.tgz", + "integrity": "sha512-QAC5i0LEb1GLG0LXDQmHu8L7FX12j0KwU/JTKmLQUJMrn04gQdKP6Du+p0QwpHb3iy71vBlqnHQ8WAfOSAWhqw==", "license": "MIT", "dependencies": { - "@babel/generator": "^8.0.0-rc.4", - "@vue-macros/common": "^3.1.1", - "@vue/devtools-api": "^8.1.1", - "ast-walker-scope": "^0.8.3", + "@babel/generator": "^8.0.0", + "@vue-macros/common": "^3.1.3", + "@vue/devtools-api": "^8.1.5", + "ast-walker-scope": "^0.9.0", "chokidar": "^5.0.0", "json5": "^2.2.3", - "local-pkg": "^1.1.2", + "local-pkg": "^1.2.1", "magic-string": "^0.30.21", - "mlly": "^1.8.0", + "mlly": "^1.8.2", "muggle-string": "^0.4.1", + "nostics": "^1.1.4", "pathe": "^2.0.3", - "picomatch": "^4.0.3", + "picomatch": "^4.0.5", "scule": "^1.3.0", - "tinyglobby": "^0.2.15", - "unplugin": "^3.0.0", - "unplugin-utils": "^0.3.1", - "yaml": "^2.8.2" + "tinyglobby": "^0.2.17", + "unplugin": "^3.3.0", + "unplugin-utils": "^0.3.2", + "yaml": "^2.9.0" }, "funding": { "url": "https://github.com/sponsors/posva" }, "peerDependencies": { "@pinia/colada": ">=0.21.2", - "@vue/compiler-sfc": "^3.5.34", - "pinia": "^3.0.4", - "vue": "^3.5.34" + "@vue/compiler-sfc": "^3.5.34 || ^4.0.0", + "pinia": "^3.0.4 || ^4.0.2", + "vite": "^7.3.0 || ^8.0.0", + "vue": "^3.5.34 || ^4.0.0" }, "peerDependenciesMeta": { "@pinia/colada": { @@ -13768,17 +13024,20 @@ }, "pinia": { "optional": true + }, + "vite": { + "optional": true } } }, "node_modules/vue-router/node_modules/@babel/generator": { - "version": "8.0.0-rc.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.0-rc.5.tgz", - "integrity": "sha512-nFZPWz3FHIS7y6rMIVoa/WBwjdutfIaRJIBQjzn+t3RnecZoRNlGmGcyR2wb0T/IgSd50Kz/6dG8/LvMCRunjg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.0.tgz", + "integrity": "sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==", "license": "MIT", "dependencies": { - "@babel/parser": "^8.0.0-rc.5", - "@babel/types": "^8.0.0-rc.5", + "@babel/parser": "^8.0.0", + "@babel/types": "^8.0.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "@types/jsesc": "^2.5.0", @@ -13789,30 +13048,30 @@ } }, "node_modules/vue-router/node_modules/@babel/helper-string-parser": { - "version": "8.0.0-rc.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0-rc.5.tgz", - "integrity": "sha512-sN7R8rBvDurfaziNfDEIjIntlazmlkCDGO4SNl2RJ3wRCn+QxspLV7hzYAE8WWVd2joVuT8sUxeePdLp2idI1A==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0.tgz", + "integrity": "sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/vue-router/node_modules/@babel/helper-validator-identifier": { - "version": "8.0.0-rc.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.0-rc.5.tgz", - "integrity": "sha512-ehJDxHvtbZ85RtX/L2fi0h9AGsBNqB5Euv1EB8RMAvGYvD+2X+QbpzzOpbklnNXO+WSZJNOaetw2BBj27xsWVg==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz", + "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==", "license": "MIT", "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/vue-router/node_modules/@babel/parser": { - "version": "8.0.0-rc.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.0-rc.5.tgz", - "integrity": "sha512-/Mfg83rK3+jsRbl4Vbd0jqxc6M1A1/WNFtgrowRM1unEsD3XcNnrBdMM0JWakd0/RN9lseQKwPduW1TiEwKOlQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.4.tgz", + "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==", "license": "MIT", "dependencies": { - "@babel/types": "^8.0.0-rc.5" + "@babel/types": "^8.0.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -13822,43 +13081,43 @@ } }, "node_modules/vue-router/node_modules/@babel/types": { - "version": "8.0.0-rc.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.0-rc.5.tgz", - "integrity": "sha512-JeSVu/m8x/zpp4CLjYHVNXuhEyOkhPXuxM8YOXjh6L4LlvQNKuUNOTo5KdBuKAcTDHw8DquToTaEkhsBqPXOaA==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz", + "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^8.0.0-rc.5", - "@babel/helper-validator-identifier": "^8.0.0-rc.5" + "@babel/helper-string-parser": "^8.0.0", + "@babel/helper-validator-identifier": "^8.0.4" }, "engines": { "node": "^22.18.0 || >=24.11.0" } }, "node_modules/vue-router/node_modules/@vue/devtools-api": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.1.2.tgz", - "integrity": "sha512-vA0O112YqyDuNA1s7Yb2gCgToQ/OxOWiFDO5ThLCcDy0ldHnSd1dUTaSYhOldbqoNgumE4dxtGAoAaSUKUD1Zg==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.2.1.tgz", + "integrity": "sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==", "license": "MIT", "dependencies": { - "@vue/devtools-kit": "^8.1.2" + "@vue/devtools-kit": "^8.2.1" } }, "node_modules/vue-router/node_modules/@vue/devtools-kit": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.1.2.tgz", - "integrity": "sha512-f75/upc+GCyjXErpgPGz4582ujS0L/adAltGy+tqXMGUJpgAcfGr6CxnnhpZY8BHuMYt6KpbF8uaFrrQG66rGQ==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", + "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", "license": "MIT", "dependencies": { - "@vue/devtools-shared": "^8.1.2", + "@vue/devtools-shared": "^8.2.1", "birpc": "^2.6.1", "hookable": "^5.5.3", "perfect-debounce": "^2.0.0" } }, "node_modules/vue-router/node_modules/@vue/devtools-shared": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.1.2.tgz", - "integrity": "sha512-X9RyVFYAdkBe4IUf5v48TxBF/6QPmF8CmWrDAjXzfUHrgQ/HGfTC1A6TqgXqZ03ye66l3AD51BAGD69IvKM9sw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", + "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", "license": "MIT" }, "node_modules/vue-router/node_modules/perfect-debounce": { @@ -13867,18 +13126,6 @@ "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", "license": "MIT" }, - "node_modules/vue-router/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/vue-sonner": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/vue-sonner/-/vue-sonner-2.0.9.tgz", @@ -13902,14 +13149,14 @@ } }, "node_modules/vue-tsc": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.2.6.tgz", - "integrity": "sha512-gYW/kWI0XrwGzd0PKc7tVB/qpdeAkIZLNZb10/InizkQjHjnT8weZ/vBarZoj4kHKbUTZT/bAVgoOr8x4NsQ/Q==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.3.8.tgz", + "integrity": "sha512-xXmYlVQpcwJDWyGlqbHrGVOl1h3UOsASymRibrHc+iy9j/UNnOrOn4u+fntHz4D6Cs74RtapeqVV6CzJeg+UlA==", "dev": true, "license": "MIT", "dependencies": { "@volar/typescript": "2.4.28", - "@vue/language-core": "3.2.6" + "@vue/language-core": "3.3.8" }, "bin": { "vue-tsc": "bin/vue-tsc.js" @@ -13919,9 +13166,9 @@ } }, "node_modules/webdriver-bidi-protocol": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz", - "integrity": "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.2.tgz", + "integrity": "sha512-VSV+fzfChirL3e7jay2yUC7B4HQCGtEWEg/MSSQbK+qWbqeGlRLlXTzPpYr3XGUvbpDHumWZBJxgesg4N7dbtA==", "dev": true, "license": "Apache-2.0" }, @@ -13933,6 +13180,8 @@ }, "node_modules/whatwg-mimetype": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", "dev": true, "license": "MIT", "engines": { @@ -13940,11 +13189,13 @@ } }, "node_modules/whence": { - "version": "2.0.2", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/whence/-/whence-2.1.0.tgz", + "integrity": "sha512-4UBPMg5mng5KLzdliVQdQ4fJwCdIMXkE8CkoDmGKRy5r8pV9xq+nVgf/sKXpmNEIOtFp7m7v2bFdb7JoLvh+Hg==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.7", - "eval-estree-expression": "^2.1.1" + "@babel/parser": "^7.28.0", + "eval-estree-expression": "^3.0.0" }, "engines": { "node": ">=14" @@ -13952,6 +13203,8 @@ }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { @@ -13966,6 +13219,8 @@ }, "node_modules/why-is-node-running": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { @@ -13981,6 +13236,8 @@ }, "node_modules/word-wrap": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { @@ -13989,21 +13246,23 @@ }, "node_modules/wordwrap": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "license": "MIT" }, "node_modules/wrap-ansi": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz", - "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.3", - "string-width": "^8.2.0", - "strip-ansi": "^7.1.2" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=20" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -14012,6 +13271,8 @@ "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { @@ -14028,27 +13289,41 @@ }, "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -14062,6 +13337,8 @@ }, "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -14071,30 +13348,10 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, "node_modules/ws": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", - "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", "dev": true, "license": "MIT", "engines": { @@ -14114,27 +13371,30 @@ } }, "node_modules/wsl-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", - "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz", + "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==", "dev": true, "license": "MIT", "dependencies": { - "is-wsl": "^3.1.0" + "is-wsl": "^3.1.0", + "powershell-utils": "^0.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/xml-name-validator": { - "version": "4.0.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/y18n": { @@ -14147,10 +13407,16 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, "node_modules/yaml": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz", - "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -14163,91 +13429,54 @@ } }, "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.1.0.tgz", + "integrity": "sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^8.0.1", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^8.2.1", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "dev": true, "license": "ISC", "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", + "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" }, "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" + "node": ">=20" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { diff --git a/frontend/package.json b/frontend/package.json index 906dd9086..0e5a8f350 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -42,7 +42,7 @@ "@types/uuid": "^11.0.0", "@unovis/vue": "^1.5.2", "@vee-validate/zod": "^4.15.1", - "@vueuse/core": "^13.9.0", + "@vueuse/core": "^14.3.0", "@zodios/core": "^10.9.6", "axios": "^1.16.1", "class-variance-authority": "^0.7.1", @@ -95,7 +95,7 @@ "codesight": "^1.18.0", "dotenv": "^17.4.2", "eslint": "^10.7.0", - "eslint-plugin-vue": "~10.8.0", + "eslint-plugin-vue": "~10.10.0", "happy-dom": "^20.8.9", "jiti": "^2.4.2", "lint-staged": "^17.0.3", diff --git a/frontend/src/typed-router.d.ts b/frontend/src/typed-router.d.ts index 32e776607..b11d0a54e 100644 --- a/frontend/src/typed-router.d.ts +++ b/frontend/src/typed-router.d.ts @@ -20,9 +20,9 @@ import type { declare module 'vue-router' { interface TypesConfig { - ParamParsers: - | never + _ParamParsers: {} RouteNamedMap: import('vue-router/auto-routes').RouteNamedMap + _RouteFileInfoMap: import('vue-router/auto-routes')._RouteFileInfoMap } } @@ -329,240 +329,320 @@ declare module 'vue-router/auto-routes' { | '/[...path]' views: | never + pathParamNames: + | 'path' } 'src/pages/crm/calls.vue': { routes: | '/crm/calls' views: | never + pathParamNames: + | never } 'src/pages/crm/companies/(index).vue': { routes: | '/crm/companies/(index)' views: | never + pathParamNames: + | never } 'src/pages/crm/companies/[id].vue': { routes: | '/crm/companies/[id]' views: | never + pathParamNames: + | 'id' } 'src/pages/crm/people/(index).vue': { routes: | '/crm/people/(index)' views: | never + pathParamNames: + | never } 'src/pages/crm/people/[id].vue': { routes: | '/crm/people/[id]' views: | never + pathParamNames: + | 'id' } 'src/pages/jobs/[id]/(index).vue': { routes: | '/jobs/[id]/(index)' views: | never + pathParamNames: + | never } 'src/pages/jobs/[id]/workshop.vue': { routes: | '/jobs/[id]/workshop' views: | never + pathParamNames: + | never } 'src/pages/jobs/create.vue': { routes: | '/jobs/create' views: | never + pathParamNames: + | never } 'src/pages/kanban.vue': { routes: | '/kanban' views: | never + pathParamNames: + | never } 'src/pages/login.vue': { routes: | '/login' views: | never + pathParamNames: + | never } 'src/pages/purchasing/mappings.vue': { routes: | '/purchasing/mappings' views: | never + pathParamNames: + | never } 'src/pages/purchasing/po/(index).vue': { routes: | '/purchasing/po/(index)' views: | never + pathParamNames: + | never } 'src/pages/purchasing/po/[id].vue': { routes: | '/purchasing/po/[id]' views: | never + pathParamNames: + | 'id' } 'src/pages/purchasing/po/create.vue': { routes: | '/purchasing/po/create' views: | never + pathParamNames: + | never } 'src/pages/purchasing/po/create-from-quote.vue': { routes: | '/purchasing/po/create-from-quote' views: | never + pathParamNames: + | never } 'src/pages/purchasing/pricing.vue': { routes: | '/purchasing/pricing' views: | never + pathParamNames: + | never } 'src/pages/purchasing/stock.vue': { routes: | '/purchasing/stock' views: | never + pathParamNames: + | never } 'src/pages/quoting/chat.vue': { routes: | '/quoting/chat' views: | never + pathParamNames: + | never } 'src/pages/reports/data-quality/archived-jobs.vue': { routes: | '/reports/data-quality/archived-jobs' views: | never + pathParamNames: + | never } 'src/pages/reports/data-quality/duplicate-identities.vue': { routes: | '/reports/data-quality/duplicate-identities' views: | never + pathParamNames: + | never } 'src/pages/reports/data-quality/duplicate-phones.vue': { routes: | '/reports/data-quality/duplicate-phones' views: | never + pathParamNames: + | never } 'src/pages/reports/job-aging.vue': { routes: | '/reports/job-aging' views: | never + pathParamNames: + | never } 'src/pages/reports/job-movement.vue': { routes: | '/reports/job-movement' views: | never + pathParamNames: + | never } 'src/pages/reports/job-profitability.vue': { routes: | '/reports/job-profitability' views: | never + pathParamNames: + | never } 'src/pages/reports/kpi.vue': { routes: | '/reports/kpi' views: | never + pathParamNames: + | never } 'src/pages/reports/payroll-reconciliation.vue': { routes: | '/reports/payroll-reconciliation' views: | never + pathParamNames: + | never } 'src/pages/reports/profit-and-loss.vue': { routes: | '/reports/profit-and-loss' views: | never + pathParamNames: + | never } 'src/pages/reports/rdti-spend.vue': { routes: | '/reports/rdti-spend' views: | never + pathParamNames: + | never } 'src/pages/reports/sales-forecast.vue': { routes: | '/reports/sales-forecast' views: | never + pathParamNames: + | never } 'src/pages/reports/sales-pipeline.vue': { routes: | '/reports/sales-pipeline' views: | never + pathParamNames: + | never } 'src/pages/reports/staff-performance.vue': { routes: | '/reports/staff-performance' views: | never + pathParamNames: + | never } 'src/pages/reports/wip.vue': { routes: | '/reports/wip' views: | never + pathParamNames: + | never } 'src/pages/schedule.vue': { routes: | '/schedule' views: | never + pathParamNames: + | never } 'src/pages/session-check.vue': { routes: | '/session-check' views: | never + pathParamNames: + | never } 'src/pages/timesheets/daily.vue': { routes: | '/timesheets/daily' views: | never + pathParamNames: + | never } 'src/pages/timesheets/entry.vue': { routes: | '/timesheets/entry' views: | never + pathParamNames: + | never } 'src/pages/timesheets/my-time.vue': { routes: | '/timesheets/my-time' views: | never + pathParamNames: + | never } 'src/pages/timesheets/weekly.vue': { routes: | '/timesheets/weekly' views: | never + pathParamNames: + | never } 'src/pages/xero.vue': { routes: | '/xero' views: | never + pathParamNames: + | never } } diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 64d5cc445..833e5475f 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -1,6 +1,17 @@ apps/job/services/kanban_categorization_service.py:0: error: Missing type arguments for generic type "List" [type-arg] apps/job/services/kanban_categorization_service.py:0: error: Missing type arguments for generic type "List" [type-arg] apps/workflow/tests/fixtures/xero_responses.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] +apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.InvoicePayload.date" is not valid as a type [valid-type] +apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] +apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.QuotePayload.date" is not valid as a type [valid-type] +apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] +apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.POPayload.date" is not valid as a type [valid-type] +apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +apps/workflow/accounting/types.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/types.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/views/xero/xero_helpers.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] @@ -33,28 +44,6 @@ apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return typ apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] -apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] -apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.InvoicePayload.date" is not valid as a type [valid-type] -apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases -apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] -apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.QuotePayload.date" is not valid as a type [valid-type] -apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases -apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] -apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.POPayload.date" is not valid as a type [valid-type] -apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases -apps/workflow/accounting/types.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/types.py:0: error: Missing type arguments for generic type "dict" [type-arg] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] @@ -238,51 +227,12 @@ docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_p docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_prerun" [attr-defined] docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_setup" untyped [untyped-decorator] docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_teardown" untyped [untyped-decorator] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "xero_id" [union-attr] -apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr] -apps/job/services/time_entry_rates.py:0: error: Incompatible return value type (got "Any | None", expected "XeroPayItem") [return-value] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/services/session_replay_service.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] apps/workflow/services/session_replay_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/services/search_telemetry.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/services/search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] apps/workflow/api/xero/client.py:0: error: Class cannot subclass "RESTClientObject" (has type "Any") [misc] apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -321,28 +271,6 @@ apps/workflow/accounting/provider.py:0: error: Missing type arguments for generi apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/timesheet/services/xero_hours.py:0: error: Incompatible return value type (got "dict[str | None, Staff]", expected "dict[str, Staff]") [return-value] -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] @@ -383,6 +311,9 @@ apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is miss apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "xero_id" [union-attr] +apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr] +apps/job/services/time_entry_rates.py:0: error: Incompatible return value type (got "Any | None", expected "XeroPayItem") [return-value] apps/job/services/job_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/services/job_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] @@ -447,53 +378,20 @@ apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types in assignment (expression has type "float | None", target has type "float") [assignment] apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types in assignment (expression has type "float | None", target has type "float") [assignment] apps/accounting/services/sales_pipeline_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Key expression in dictionary comprehension has incompatible type "str | None"; expected type "str" [misc] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] apps/accounting/services/invoice_calculation.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] -apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] -apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] -apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] -apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] -apps/workflow/services/llm_service.py:0: note: Possible overload variants: -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str -apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/services/dev_demo_export_scrubber.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/tests/test_xero_pay_item.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_pay_item.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_pay_item.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -518,6 +416,42 @@ apps/workflow/tests/test_xero_app_model.py:0: error: Function is missing a retur apps/workflow/tests/test_xero_app_model.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_api_schema_coverage.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -536,124 +470,10 @@ apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] -apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value -apps/process/services/form_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/form_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Call to untyped function "get_default_cost_set_summary" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "Callable[..., Any] | str | None") [assignment] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers_scheduled_tasks.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/quoting/serializers_scheduled_tasks.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/quote_spreadsheet_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/views/build_id_view.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/reports/pnl.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -699,6 +519,28 @@ apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Co apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value apps/quoting/mcp.py:0: error: Class cannot subclass "ModelQueryToolset" (has type "Any") [misc] apps/quoting/mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/quoting/mcp.py:0: error: Class cannot subclass "MCPToolset" (has type "Any") [misc] @@ -717,15 +559,54 @@ apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase apps/quoting/mcp.py:0: error: Need type annotation for "supplier_prices" (hint: "supplier_prices: dict[, ] = ...") [var-annotated] +apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] +apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value +apps/process/services/form_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/form_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] apps/operations/services/scheduler_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] +apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Call to untyped function "get_default_cost_set_summary" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/services/job_profitability_report.py:0: error: Call to untyped function "_get_queryset" in typed context [no-untyped-call] apps/job/services/job_profitability_report.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/services/job_profitability_report.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] @@ -788,52 +669,9 @@ apps/job/services/data_integrity_service.py:0: error: Dict entry 4 has incompati apps/job/services/data_integrity_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] -apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int -apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T -apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] -apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_dev_demo_export.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -841,6 +679,12 @@ apps/workflow/tests/test_dev_demo_export.py:0: note: Use "-> None" if function d apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/process/tests/test_form_service.py:0: note: Use "-> None" if function does not return a value @@ -859,6 +703,39 @@ apps/process/tests/test_form_service.py:0: error: Call to untyped function "_mak apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/process/tests/test_form_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] +apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] +apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -981,25 +858,6 @@ apps/accounting/services/core.py:0: error: Unsupported left operand type for / ( apps/accounting/services/core.py:0: note: Both left and right operands are unions apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] -apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] -apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance -apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] -apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] -apps/job/services/kanban_service.py:0: error: Call to untyped function "filter_kanban_jobs" of "KanbanService" in typed context [no-untyped-call] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "QuerySet[Job, Job]" [no-any-return] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Call to untyped function "filter_kanban_jobs" of "KanbanService" in typed context [no-untyped-call] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/testing.py:0: note: Use "-> None" if function does not return a value apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1026,7 +884,7 @@ apps/workflow/serializers.py:0: error: Function is missing a type annotation [n apps/workflow/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Field" defined the type as "dict[str, Any]") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1064,6 +922,10 @@ apps/workflow/serializers.py:0: error: Missing type arguments for generic type " apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1212,12 +1074,30 @@ apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers_scheduled_tasks.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/quoting/serializers_scheduled_tasks.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1278,17 +1158,31 @@ apps/process/tests/test_form_api.py:0: error: Function is missing a type annotat apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/quote_spreadsheet_serializer.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/kanban_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1343,15 +1237,109 @@ apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/accounting/serializers/rdti_spend_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] +apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] +apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance +apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] +apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] +apps/job/services/kanban_service.py:0: error: Call to untyped function "filter_kanban_jobs" of "KanbanService" in typed context [no-untyped-call] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "QuerySet[Job, Job]" [no-any-return] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Call to untyped function "filter_kanban_jobs" of "KanbanService" in typed context [no-untyped-call] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/data_versions_view.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/build_id_view.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/api/reports/pnl.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1438,131 +1426,6 @@ apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | Non apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Argument "row_date" to "build_row" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: note: Use "-> None" if function does not return a value -apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value -apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] -apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] -apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] -apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] -apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Key expression in dictionary comprehension has incompatible type "str | None"; expected type "str" [misc] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2355,11 +2218,105 @@ apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a retu apps/accounting/tests/test_core_nplusone.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounting/tests/test_core_nplusone.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_files_collection_view.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Call to untyped function "save_file" in typed context [no-untyped-call] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_thumbnail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] +apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] @@ -2491,132 +2448,58 @@ apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a r apps/job/tests/test_kanban_reorder_priority.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_files_collection_view.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Call to untyped function "save_file" in typed context [no-untyped-call] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_thumbnail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] -apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value +apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/mixins.py:0: error: Call to untyped function "get_job_by_number" in typed context [no-untyped-call] apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/mixins.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -2649,7 +2532,7 @@ apps/purchasing/serializers.py:0: error: Missing type arguments for generic type apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "Callable[..., Any] | str | None") [assignment] +apps/purchasing/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -2785,60 +2668,22 @@ apps/job/serializers/job_serializer.py:0: error: Missing type arguments for gene apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2863,184 +2708,95 @@ apps/company/tests/test_company_fts_search.py:0: error: Function is missing a ty apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_fts_search.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Staff | AnonymousUser") [assignment] apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/chat_service.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] -apps/job/services/chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/chat_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/chat_service.py:0: error: Cannot call function of unknown type [operator] -apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Argument "document_type" to "create_blank_procedure" of "ProcedureService" has incompatible type "Sequence[str]"; expected "str" [arg-type] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "update" of "ProcedureViewSet" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "dict[str, Any]") [assignment] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] -apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] -apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "ModelSerializer" [type-arg] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value +apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value +apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value +apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] +apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] +apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] +apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -3068,366 +2824,41 @@ apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a re apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] -apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/auth.py:0: error: Call to untyped function "RateLimitedRESTClient" in typed context [no-untyped-call] -apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "dict[str, Any] | None" [no-any-return] -apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/api/xero/active_app.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "get_or_fetch_company" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_log_invoice_sync_events" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "recalculate_job_invoicing_state" has incompatible type "UUID"; expected "str" [arg-type] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "po_number" of "PurchaseOrder" (got "Any | None", expected "str | int | Combinable") [misc] -apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "order_date" of "PurchaseOrder" (got "Any | None", expected "str | date | Combinable") [misc] -apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] -apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] -apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Incompatible type for lookup 'xero_id': (got "Any | None", expected "UUID | str") [misc] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/xero/stock_sync.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "Stock") [assignment] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Call to untyped function "get_or_fetch_company" in typed context [no-untyped-call] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Call to untyped function "sync_time_entries_bulk" in typed context [no-untyped-call] -apps/workflow/api/xero/push.py:0: error: Call to untyped function "sync_expense_entries_bulk" in typed context [no-untyped-call] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] -apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] -apps/workflow/api/xero/payroll.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "date") [assignment] -apps/workflow/api/xero/payroll.py:0: error: Returning Any from function declared to return "date | None" [no-any-return] -apps/workflow/api/xero/payroll.py:0: error: Incompatible default for parameter "payment_date" (default has type "None", parameter has type "date") [assignment] -apps/workflow/api/xero/payroll.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/workflow/api/xero/payroll.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Argument "employee_id" to "post_timesheet" has incompatible type "str"; expected "UUID" [arg-type] -apps/workflow/api/xero/payroll.py:0: error: Need type annotation for "leave_ids" (hint: "leave_ids: list[] = ...") [var-annotated] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Incompatible return value type (got "list[str]", expected "int") [return-value] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "get_all_xero_contacts" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Unsupported operand types for + ("object" and "int") [operator] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "sync_job_to_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Unsupported operand types for + ("object" and "int") [operator] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Dict entry 0 has incompatible type "str": "int"; expected "str": "str" [dict-item] -apps/workflow/api/xero/seed.py:0: error: Argument 1 to "update" of "MutableMapping" has incompatible type "dict[str, str] | dict[str, bool]"; expected "SupportsKeysAndGetItem[str, str]" [arg-type] -apps/workflow/api/xero/seed.py:0: error: Incompatible types in assignment (expression has type "int", target has type "str") [assignment] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_last_modified_time" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "update_sync_cursor" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_sync_cursor" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_local_stock_to_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] -apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_access_logging_middleware.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_access_logging_middleware.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: note: Use "-> None" if function does not return a value +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: note: Use "-> None" if function does not return a value +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] +apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -3566,12 +2997,6 @@ apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_sta apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/job/services/job_rest_service.py:0: error: Value of type "JobDeltaRejection@AnnotatedWith[TypedDict({'occurrence_count': int, 'first_seen': Any, 'last_seen': Any, 'latest_id': Any})]" is not indexable [index] -apps/job/services/job_rest_service.py:0: error: Value of type "JobDeltaRejection@AnnotatedWith[TypedDict({'occurrence_count': int, 'first_seen': Any, 'last_seen': Any, 'latest_id': Any})]" is not indexable [index] -apps/job/services/job_rest_service.py:0: error: Value of type "JobDeltaRejection@AnnotatedWith[TypedDict({'occurrence_count': int, 'first_seen': Any, 'last_seen': Any, 'latest_id': Any})]" is not indexable [index] -apps/job/services/job_rest_service.py:0: error: Value of type "JobDeltaRejection@AnnotatedWith[TypedDict({'occurrence_count': int, 'first_seen': Any, 'last_seen': Any, 'latest_id': Any})]" is not indexable [index] -apps/job/services/job_rest_service.py:0: error: Value of type "JobDeltaRejection@AnnotatedWith[TypedDict({'occurrence_count': int, 'first_seen': Any, 'last_seen': Any, 'latest_id': Any})]" is not indexable [index] -apps/job/services/job_rest_service.py:0: error: Value of type "JobDeltaRejection@AnnotatedWith[TypedDict({'occurrence_count': int, 'first_seen': Any, 'last_seen': Any, 'latest_id': Any})]" is not indexable [index] apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] @@ -3583,173 +3008,8 @@ apps/job/services/job_rest_service.py:0: error: Incompatible default for paramet apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] -apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_quote" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_purchase_order" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/services/xero_sync_service.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] -apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/services/xero_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Too many arguments for "get_authentication_url" [call-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] -apps/timesheet/views/api.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Call to untyped function "build_timesheet_response" in typed context [no-untyped-call] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] -apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Need type annotation for "updated_line_ids" (hint: "updated_line_ids: set[] = ...") [var-annotated] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] -apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/workflow/tests/test_access_logging_middleware.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_access_logging_middleware.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -3818,259 +3078,6 @@ apps/job/tests/test_event_deduplication.py:0: error: Function is missing a retur apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_event_deduplication.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_contact" in typed context [no-untyped-call] -apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_invoice" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Argument 1 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument 3 to "exchange_code_for_token" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Returning Any from function declared to return "HttpResponse" [no-any-return] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible return value type (got "JsonResponse", expected "StreamingHttpResponse") [return-value] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "generate_xero_sync_events" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentSuccessResponseSerializer", variable has type "XeroDocumentErrorResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "xero_invoice_id" to "XeroInvoiceManager" has incompatible type "UUID"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_reset_scrub_schema" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run_pipe" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_reset_scrub_schema" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_accounts" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_contacts" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_projects" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_employees" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_invoices" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_quotes" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_stock_items" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "seed_companies_to_xero" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "seed_jobs_to_xero" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_batch_create_invoices" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_get_invoice_line_unit_amount" of "Command" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_build_invoice_payload" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_batch_create_quotes" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_build_quote_payload" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Item "None" of "str | None" has no attribute "endswith" [union-attr] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_users" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_employees" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_rates" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_calendars" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_leave_types" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_pay_runs" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "configure_payroll" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "link_staff" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "create_staff" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_tenants" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_tenants" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_employees_simple_dev" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "_print_link_staff_summary" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "_print_create_staff_summary" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Module "apps.purchasing.services.purchasing_rest_service" does not explicitly export attribute "PreconditionFailedError" [attr-defined] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_none_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Dict entry 1 has incompatible type "str": "str"; expected "str": "bool" [dict-item] -apps/purchasing/views/purchasing_rest_views.py:0: error: Dict entry 1 has incompatible type "str": "str"; expected "str": "bool" [dict-item] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Need type annotation for "allocations_by_line" (hint: "allocations_by_line: dict[, ] = ...") [var-annotated] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "PurchaseOrderLine | None" has no attribute "id" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Generator has incompatible item type "int"; expected "bool" [misc] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "create_purchase_order_pdf" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -4213,14 +3220,898 @@ apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "up apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] +apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] +apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] +apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] +apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] +apps/workflow/services/llm_service.py:0: note: Possible overload variants: +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str +apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value +apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] +apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/job/services/chat_service.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] +apps/job/services/chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/chat_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/services/chat_service.py:0: error: Cannot call function of unknown type [operator] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Argument "document_type" to "create_blank_procedure" of "ProcedureService" has incompatible type "Sequence[str]"; expected "str" [arg-type] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "update" of "ProcedureViewSet" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] +apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value +apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/auth.py:0: error: Call to untyped function "RateLimitedRESTClient" in typed context [no-untyped-call] +apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "dict[str, Any] | None" [no-any-return] +apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/api/xero/active_app.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "get_or_fetch_company" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_log_invoice_sync_events" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "recalculate_job_invoicing_state" has incompatible type "UUID"; expected "str" [arg-type] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "po_number" of "PurchaseOrder" (got "Any | None", expected "str | int | Combinable") [misc] +apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "order_date" of "PurchaseOrder" (got "Any | None", expected "str | date | Combinable") [misc] +apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Any | None"; expected "str" [arg-type] +apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Any | None"; expected "str" [arg-type] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] +apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] +apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Incompatible type for lookup 'xero_id': (got "Any | None", expected "UUID | str") [misc] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/api/xero/stock_sync.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "Stock") [assignment] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Call to untyped function "get_or_fetch_company" in typed context [no-untyped-call] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Call to untyped function "sync_time_entries_bulk" in typed context [no-untyped-call] +apps/workflow/api/xero/push.py:0: error: Call to untyped function "sync_expense_entries_bulk" in typed context [no-untyped-call] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] +apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] +apps/workflow/api/xero/payroll.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "date") [assignment] +apps/workflow/api/xero/payroll.py:0: error: Returning Any from function declared to return "date | None" [no-any-return] +apps/workflow/api/xero/payroll.py:0: error: Incompatible default for parameter "payment_date" (default has type "None", parameter has type "date") [assignment] +apps/workflow/api/xero/payroll.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/workflow/api/xero/payroll.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Argument "employee_id" to "post_timesheet" has incompatible type "str"; expected "UUID" [arg-type] +apps/workflow/api/xero/payroll.py:0: error: Need type annotation for "leave_ids" (hint: "leave_ids: list[] = ...") [var-annotated] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/workflow/api/xero/payroll.py:0: error: Incompatible return value type (got "list[str]", expected "int") [return-value] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_last_modified_time" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "update_sync_cursor" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_sync_cursor" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_local_stock_to_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "get_all_xero_contacts" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Unsupported operand types for + ("object" and "int") [operator] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "sync_job_to_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Unsupported operand types for + ("object" and "int") [operator] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Dict entry 0 has incompatible type "str": "int"; expected "str": "str" [dict-item] +apps/workflow/api/xero/seed.py:0: error: Argument 1 to "update" of "MutableMapping" has incompatible type "dict[str, str] | dict[str, bool]"; expected "SupportsKeysAndGetItem[str, str]" [arg-type] +apps/workflow/api/xero/seed.py:0: error: Incompatible types in assignment (expression has type "int", target has type "str") [assignment] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] +apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_quote" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_purchase_order" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/services/xero_sync_service.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] +apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/services/xero_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Too many arguments for "get_authentication_url" [call-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/timesheet/views/api.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Call to untyped function "build_timesheet_response" in typed context [no-untyped-call] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Need type annotation for "updated_line_ids" (hint: "updated_line_ids: set[] = ...") [var-annotated] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] +apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] +apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] +apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int +apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T +apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] +apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_contact" in typed context [no-untyped-call] +apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_invoice" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Argument 1 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 3 to "exchange_code_for_token" has incompatible type "Any | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Returning Any from function declared to return "HttpResponse" [no-any-return] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible return value type (got "JsonResponse", expected "StreamingHttpResponse") [return-value] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "generate_xero_sync_events" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentSuccessResponseSerializer", variable has type "XeroDocumentErrorResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "xero_invoice_id" to "XeroInvoiceManager" has incompatible type "UUID"; expected "str | None" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] +apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Module "apps.purchasing.services.purchasing_rest_service" does not explicitly export attribute "PreconditionFailedError" [attr-defined] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_none_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Dict entry 1 has incompatible type "str": "str"; expected "str": "bool" [dict-item] +apps/purchasing/views/purchasing_rest_views.py:0: error: Dict entry 1 has incompatible type "str": "str"; expected "str": "bool" [dict-item] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Need type annotation for "allocations_by_line" (hint: "allocations_by_line: dict[, ] = ...") [var-annotated] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "PurchaseOrderLine | None" has no attribute "id" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Generator has incompatible item type "int"; expected "bool" [misc] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "create_purchase_order_pdf" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] apps/workflow/xero_webhooks.py:0: error: "Callable[[str, dict[str, Any]], None]" has no attribute "delay" [attr-defined] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -4337,31 +4228,112 @@ apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderMan apps/workflow/tests/test_xero_po_manager.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_po_manager.py:0: error: "XeroPurchaseOrderManagerConstructionTests" has no attribute "purchase_order" [attr-defined] apps/workflow/tests/test_xero_app_active.py:0: error: Value of type "dict[str, Any] | None" is not indexable [index] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "analyze_fields" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run_pipe" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Item "None" of "IO[bytes] | None" has no attribute "close" [union-attr] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Need type annotation for "field_samples" [var-annotated] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "cannot_be_pii" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "is_uuid_string" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_accounts" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_contacts" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_projects" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_employees" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_invoices" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_quotes" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_stock_items" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "seed_companies_to_xero" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "seed_jobs_to_xero" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_batch_create_invoices" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_get_invoice_line_unit_amount" of "Command" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_build_invoice_payload" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_batch_create_quotes" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_build_quote_payload" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Item "None" of "str | None" has no attribute "endswith" [union-attr] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_seed_xero_from_database.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_seed_xero_from_database.py:0: error: Incompatible types in assignment (expression has type "StringIO", variable has type "OutputWrapper") [assignment] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_users" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_employees" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_rates" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_calendars" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_leave_types" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_pay_runs" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "configure_payroll" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "link_staff" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "create_staff" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_tenants" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_tenants" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_employees_simple_dev" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "_print_link_staff_summary" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "_print_create_staff_summary" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value +apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -4382,15 +4354,35 @@ apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a t apps/workflow/tests/test_xero_setup_command.py:0: error: Cannot assign to a method [method-assign] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: note: Use "-> None" if function does not return a value -apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_reset_scrub_schema" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run_pipe" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_reset_scrub_schema" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "analyze_fields" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run_pipe" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Item "None" of "IO[Any] | None" has no attribute "close" [union-attr] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Need type annotation for "field_samples" [var-annotated] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "cannot_be_pii" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "is_uuid_string" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] diff --git a/poetry.lock b/poetry.lock index c5934485d..8ab01e8ee 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,145 +2,145 @@ [[package]] name = "aiohappyeyeballs" -version = "2.6.1" +version = "2.7.1" description = "Happy Eyeballs for asyncio" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"}, - {file = "aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558"}, + {file = "aiohappyeyeballs-2.7.1-py3-none-any.whl", hash = "sha256:9243213661e29250eb41368e5daa826fc017156c3b8a11440826b2e3ed376472"}, + {file = "aiohappyeyeballs-2.7.1.tar.gz", hash = "sha256:065665c041c42a5938ed220bdcd7230f22527fbec085e1853d2402c8a3615d9d"}, ] [[package]] name = "aiohttp" -version = "3.14.1" +version = "3.14.3" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.10" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "aiohttp-3.14.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8f6bb621e5863cfe8fe5ff5468002d200ec31f30f1280b259dc505b02595099e"}, - {file = "aiohttp-3.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4f7215cb3933784f79ed20e5f050e15984f390424339b22375d5a53c933a0491"}, - {file = "aiohttp-3.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9d4e294455b23a68c9b8f042d0e8e377a265bcb15332753695f6e5b6819e0ce"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b238af795833d5731d049d82bc84b768ae6f8f97f0495963b3ed9935c5901cc3"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e4e5e0ae56914ecdbf446493addefc0159053dd53962cef37d7839f37f73d505"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:092e4ce3619a7c6dee52a6bdabda973d9b34b66781f840ce93c7e0cec30cf521"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb33777ea21e8b7ecde0e6fc84f598be0a1192eab1a63bc746d75aa75d38e7bd"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23119f8fd4f5d16902ed459b63b100bcd269628075162bddac56cc7b5273b3fb"}, - {file = "aiohttp-3.14.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:57fc6745a4b7d0f5a9eb4f40a69718be6c0bc1b8368cc9fe89e90118719f4f42"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6fd35beba67c4183b09375c5fff9accb47524191a244a99f95fd4472f5402c2b"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:672b9d65f42eb877f5c3f234a4547e4e1a226ca8c2eed879bb34670a0ce51192"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:24ba13339fed9251d9b1a1bec8c7ab84c0d1675d79d33501e11f94f8b9a84e05"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:94da27378da0610e341c4d30de29a191672683cc82b8f9556e8f7c7212a020fe"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:52cdac9432d8b4a719f35094a818d95adcae0f0b4fe9b9b921909e0c87de9e7d"}, - {file = "aiohttp-3.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:672ac254412a24d0d0cf00a9e6c238877e4be5e5fa2d188832c1244f45f31966"}, - {file = "aiohttp-3.14.1-cp310-cp310-win32.whl", hash = "sha256:2fe3607e71acc6ebb0ec8e492a247bf7a291226192dc0084236dfc12478916f6"}, - {file = "aiohttp-3.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:30099eda75a53c32efb0920e9c33c195314d2cc1c680fbfd30894932ac5f27df"}, - {file = "aiohttp-3.14.1-cp310-cp310-win_arm64.whl", hash = "sha256:5a837f49d901f9e368651b676912bff1104ed8c1a83b280bcd7b29adccef5c9c"}, - {file = "aiohttp-3.14.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:aa00140699487bd435fde4342d85c94cb256b7cd3a5b9c3396c67f19922afda2"}, - {file = "aiohttp-3.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c1af67559445498b502030c35c59db59966f47041ca9de5b4e707f86bd10b5f"}, - {file = "aiohttp-3.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d44ec478e713ee7f29b439f7eb8dc2b9d4079e11ae114d2c2ac3d5daf30516c8"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d3b1a184a9a8f548a6b73f1e26b96b052193e4b3175ed7342aaf1151a1f00a04"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5f2504bc0322437c9a1ff6d3333ca56c7477b727c995f036b976ae17b98372c8"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73f05ea02013e02512c3bf42714f1208c57168c779cc6fe23516e4543089d0a6"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:797457503c2d426bee06eef808d07b31ede30b65e054444e7de64cad0061b7af"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b821a1f7dedf7e37450654e620038ac3b2e81e8fa6ea269337e97101978ec730"}, - {file = "aiohttp-3.14.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4cd96b5ba05d67ed0cf00b5b405c8cd99586d8e3481e8ee0a831057591af7621"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d459b98a932296c6f0e94f87511a0b1b90a8a02c30a50e60a297619cd5a58ee"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:764457a7be60825fb770a644852ff717bcbb5042f189f2bd16df61a81b3f6573"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f7a16ef45b081454ef844502d87a848876c490c4cb5c650c230f6ec79ed2c1e7"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2fbc3ed048b3475b9f0cbcb9978e9d2d3511acd91ead203af26ed9f0056004cf"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bedb0cd073cc2dc035e30aeb99444389d3cd2113afe4ef9fcd23d439f5bade85"}, - {file = "aiohttp-3.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b6feea921016eb3d4e04d65fc4e9ca402d1a3801f562aef94989f54694917af3"}, - {file = "aiohttp-3.14.1-cp311-cp311-win32.whl", hash = "sha256:313701e488100074ce99850404ee36e741abf6330179fec908a1944ecf570126"}, - {file = "aiohttp-3.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:03ab4530fdcb3a543a122ba4b65ac9919da9fe9f78a03d328a6e38ff962f7aa5"}, - {file = "aiohttp-3.14.1-cp311-cp311-win_arm64.whl", hash = "sha256:486f7d16ed54c39c2cbd7ca71fd8ba2b8bb7860df65bd7b6ed640bab96a38a8b"}, - {file = "aiohttp-3.14.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d35143e27778b4bb0fb189562d7f275bff79c62ab8e98459717c0ea617ff2480"}, - {file = "aiohttp-3.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bcfb80a2cc36fba2534e5e5b5264dc7ae6fcd9bf15256da3e53d2f499e6fa29d"}, - {file = "aiohttp-3.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:27fd7c91e51729b4f7e1577865fa6d34c9adccbc39aabe9000285b48af9f0ec2"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c567bf9eaf664280116a8688f63016e6b32db2505908e2bdaca1b6438142f2"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f5e6ff2bdbb8f4cd3fbe41f99e25bbcd58e3bf9f13d3dd31a11e7917251cc77a"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2f73e01dc37122325caf079982621262f96d74823c179038a82fddfc50359264"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bb2c0c80d431c0d03f2c7dbf125150fedd4f0de17366a7ca33f7ccb822391842"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e6fc1a85fa7194a1a7d19f44e8609180f4a8eb5fa4c7ed8b4355f080fad235c"}, - {file = "aiohttp-3.14.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:686b6c0d3911ec387b444ddf5dc62fb7f7c0a7d5186a7861626496a5ab4aff95"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c6fa4dc7ad6f8109c70bb1499e589f76b0b792baf39f9b017eb92c8a81d0a199"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:87a5eea1b2a5e21e1ebdbb33ad4165359189327e63fc4e4894693e7f821ac817"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c1421eb01d4fd608d88cc8290211d177a58532b55ad94076fb349c5bf467f0a"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:34b257ec41345c1e8f2df68fa908a7952f5de932723871eb633ecbbff396c9a4"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:de538791a80e5d862addbc183f70f0158ac9b9bb872bb147f1fd2a683691e087"}, - {file = "aiohttp-3.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6f71173be42d3241d428f760122febb748de0623f44308a6f120d0dd9ec572e3"}, - {file = "aiohttp-3.14.1-cp312-cp312-win32.whl", hash = "sha256:ec8dc383ee57ea3e883477dcca3f11b65d58199f1080acaf4cd6ad9a99698be4"}, - {file = "aiohttp-3.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2aa92c87868cd13674989f9ee83e5f9f7ea4237589b728048e1f0c8f6caa3271"}, - {file = "aiohttp-3.14.1-cp312-cp312-win_arm64.whl", hash = "sha256:2c840c90759922cb5e6dda94596e079a30fb5a5ba548e7e0dc00574703940847"}, - {file = "aiohttp-3.14.1-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:b3a03285a7f9c7b016324574a6d92a1c895da6b978cb8f1deee3ac72bc6da178"}, - {file = "aiohttp-3.14.1-cp313-cp313-android_21_x86_64.whl", hash = "sha256:2a73f487ab8ef5abbb24b7aa9b73e98eaba9e9e031804ff2416f02eca315ccaf"}, - {file = "aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:915fbb7b41b115192259f8c9ae58f3ddc444d2b5579917270211858e606a4afd"}, - {file = "aiohttp-3.14.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:7fb4bdf95b0561a79f259f9d28fbc109728c5ee7f27aff6391f0ca703a329abe"}, - {file = "aiohttp-3.14.1-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1b9748363260121d2927704f5d4fc498150669ca3ae93625986ee89c8f80dcd4"}, - {file = "aiohttp-3.14.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:86a6dab78b0e43e2897a3bbe15745aa60dc5423ca437b7b0b164c069bf91b876"}, - {file = "aiohttp-3.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4dfd6e47d3c44c2279907607f73a4240b88c69eb8b90da7e2441a8045dfd21da"}, - {file = "aiohttp-3.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:317acd9f8602858dc7d59679812c376c7f0b97bcbbf16e0d6237f54141d8a8a6"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd869c427324e5cb15195793de951295710db28be7d818247f3097b4ab5d4b96"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93b032b5ec3255473c143627d21a69ac74ae12f7f33974cb587c564d11b1066f"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f234b4deb12f3ad59127e037bc57c40c21e45b45282df7d3a55a0f409f595296"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9af6779bfb46abf124068327abcdf9ce95c9ef8287a3e8da76ccf2d0f16c28fa"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:faccab372e66bc76d5731525e7f1143c922271725b9d38c9f97edcc66266b451"}, - {file = "aiohttp-3.14.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f380468b09d2a81633ee863b0ec5648d364bd17bb8ecfb8c2f387f7ac1faf42c"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:97e704dcd26271f5bda3fa07c3ce0fb76d6d3f8659f4baa1a24442cc9ba177ca"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:269b76ac5394092b95bc4a098f4fc6c191c083c3bd12775d1e30e663132f6a09"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5c0b3e614340c889d575451696374c9d17affd54cd607ca0babed8f8c37b9397"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5663ee9257cfa1add7253a7da3035a02f31b6600ec48261585e1800a81533080"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:603a2c834142172ffddc054067f5ec0ca65d57a0aa98a71bc81952573208e345"}, - {file = "aiohttp-3.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cb21957bb8aca671c1765e32f58164cf0c50e6bf41c0bbbd16da20732ecaf588"}, - {file = "aiohttp-3.14.1-cp313-cp313-win32.whl", hash = "sha256:e509a55f681e6158c20f70f102f9cf61fb20fbc382272bc6d94b7343f2582780"}, - {file = "aiohttp-3.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:1ac8531b638959718e18c2207fbfe297819875da46a740b29dfa29beba64355a"}, - {file = "aiohttp-3.14.1-cp313-cp313-win_arm64.whl", hash = "sha256:250d14af67f6b6a1a4a811049b1afa69d61d617fca6bf33149b3ab1a6dbcf7b8"}, - {file = "aiohttp-3.14.1-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:7c106c26852ca1c2047c6b80384f17100b4e439af276f21ef3d4e2f450ae7e15"}, - {file = "aiohttp-3.14.1-cp314-cp314-android_24_x86_64.whl", hash = "sha256:20205f7f5ade7aaec9f4b500549bbc071b046453aed72f9c06dcab87896a83e8"}, - {file = "aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:62a759436b29e677181a9e76bab8b8f689a29cb9c535f45f7c48c9c830d3f8c3"}, - {file = "aiohttp-3.14.1-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:2964cbf553df4d7a57348da44d961d871895fc1ee4e8c322b2a95612c7b17fba"}, - {file = "aiohttp-3.14.1-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:237651caadc3a59badd39319c54642b5299e9cc98a3a194310e55d5bb9f5e397"}, - {file = "aiohttp-3.14.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:896e12dfdbbab9d8f7e16d2b28c6769a60126fa92095d1ebf9473d02593a2448"}, - {file = "aiohttp-3.14.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d03f281ed22579314ba00821ce20115a7c0ac430660b4cc05704a3f818b3e004"}, - {file = "aiohttp-3.14.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07eabb979d236335fed927e137a928c9adfb7df3b9ec7aa31726f133a62be983"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4fe1f1087cbadb280b5e1bb054a4f00d1423c74d6626c5e48400d871d34ecefe"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:367a9314fdc79dab0fac96e216cb41dd73c85bdca85306ce8999118ba7e0f333"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a24f677ebe83749039e7bdf862ff0bbb16818ae4193d4ef96505e269375bcce0"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c83afe0ba876be7e943d2e0ba645809ad441575d2840c895c21ee5de93b9377a"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:634e385930fb6d2d479cf3aa66515955863b77a5e3c2b5894ca259a25b308602"}, - {file = "aiohttp-3.14.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeea07c4397bbc57719c4eed8f9c284874d4f175f9b6d57f7a1546b976d455ca"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:335c0cc3e3545ce98dcb9cfcb836f40c3411f43fa03dab757597d80c89af8a35"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:ae6be797afdef264e8a84864a85b196ca06045586481b3df8a967322fd2fa844"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:8560b4d712474335d08907db7973f71912d3a9a8f1dee992ec06b5d2fe359496"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7edd08e0a5deb1e8564a2fcd8f4561014a3f05252334671bbf55ddd47db0e5"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:b6ff7fcee63287ae57b5df3e4f5957ce032122802509246dec1a5bcc55904c95"}, - {file = "aiohttp-3.14.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6ffbb2f4ec1ceaff7e07d43922954da26b223d188bf30658e561b98e23089444"}, - {file = "aiohttp-3.14.1-cp314-cp314-win32.whl", hash = "sha256:a9875b46d910cff3ea2f5962f9d266b465459fe634e22556ab9bd6fc1192eea0"}, - {file = "aiohttp-3.14.1-cp314-cp314-win_amd64.whl", hash = "sha256:af8b4b81a960eeaf1234971ac3cd0ba5901f3cd42eae42a46b4d089a8b492719"}, - {file = "aiohttp-3.14.1-cp314-cp314-win_arm64.whl", hash = "sha256:cf4491381b1b57425c315a56a439251b1bdac07b2275f19a8c44bc57744532ec"}, - {file = "aiohttp-3.14.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:819c054312f1af92947e6a55883d1b66feefab11531a7fc45e0fb9b63880b5c2"}, - {file = "aiohttp-3.14.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10ee9c1753a8f706345b22496c79fbddb5be0599e0823f3738b1534058e25340"}, - {file = "aiohttp-3.14.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1601cc37baf5750ccacae618ec2daf020769581695550e3b654a911f859c563d"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d6e0ac9da31c9c04c84e1c0182ad8d6df35965a85cae29cd71d089621b3ae94"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e8f2d660c350b3d0e259c7a7e3d9b7fc8b41210cbcc3d4a7076ff0a5e5c2fdc"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4691802dda97be727f79d86818acaad7eb8e9252626a1d6b519fedbb92d5e251"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c389c482a7e9b9dc3ee2701ac46c4125297a3818875b9c305ddb603c04828fd1"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fc0cacab7ba4e56f0f81c82a98c09bed2f39c940107b03a34b168bdf7597edd3"}, - {file = "aiohttp-3.14.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:979ed4717f59b8bb12e3963378fa285d93d367e15bcd66c721311826d3c44a6c"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:38e1e7daaea81df51c952e18483f323d878499a1e2bfe564790e0f9701d6f203"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4132e72c608fe9fecb8f409113567605915b83e9bdd3ea56538d2f9cd35002f1"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:eefd9cc9b6d4a2db5f00a26bc3e4f9acf71926a6ec557cd56c9c6f27c290b665"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b165790117eea512d7f3fb22f1f6dad3d55a7189571993eb015591c1401276d1"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:ed09c7eb1c391271c2ed0314a51903e72a3acb653d5ccfc264cdf3ef11f8269d"}, - {file = "aiohttp-3.14.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:99abd37084b82f5830c635fddd0b4993b9742a66eb746dacf433c8590e8f9e3c"}, - {file = "aiohttp-3.14.1-cp314-cp314t-win32.whl", hash = "sha256:47ddf841cdecc810749921d25606dee45857d12d2ad5ddb7b5bd7eab12e4b365"}, - {file = "aiohttp-3.14.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5e78b522b7a6e27e0b25d19b247b75039ac4c94f99823e3c9e53ae1603a9f7e9"}, - {file = "aiohttp-3.14.1-cp314-cp314t-win_arm64.whl", hash = "sha256:90d53f1609c29ccc2193945ef732428382a28f78d0456ae4d3daf0d48b74f0f6"}, - {file = "aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035"}, + {file = "aiohttp-3.14.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:eb0495d778817619273c108784292be161a924b9f5ae5cbbc70a2caa6838250b"}, + {file = "aiohttp-3.14.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3c200cf9757edd785051dc699c7ecbec22110dbfcb3fefc7a9f9695eda8ea7a"}, + {file = "aiohttp-3.14.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd51ebf9d3a00c074df4ede271023f4d2dba289bcc740b88191872716014e3c5"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:134ac5ddcf61c6fad984b9a5727d83492ada43d63471db20fb73042c13fca62f"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:70c987b27534f9ae1a723f47ae921571d616da21d3208282bf4c52af5164ac43"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1b59533861b70a2185c8f4f350f791f39d64358ef6944ce71c5240c9ec0982c9"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1c5281acc88b92396f88c7e1e2748f8466689df22b80170e4f51efa712fb47a8"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48d67b87db6279c044760787eb01f6413032c2e6f3ba1cafaa492b1c8e578479"}, + {file = "aiohttp-3.14.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f53bcd52f585e1ac3e590d61434eb61f9a88c38df041b4ea126d97144344a77b"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0fdea2281997af69da84c77ffa6f5938a0285f21fb3887c249d67419ca865b3d"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:cda5fd5c95ad7a125a2e8464acc78b98b94c475a3780d6aa0aa157c93f470f4d"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:6debfa7312ff9d4c124dc71d72e9a0a4b9e0879e48ba6fcb42bef5c3300289e2"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:f4e05329faa0ea1a404b37de4f034fd2c2defcca06a68dc6745e4e56c88e8a48"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a3a8296e7ab5c295f53f1041487cb088e1480775aafbf7fe545d93b770a0f96f"}, + {file = "aiohttp-3.14.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5373dc80ad1aa2fb9ad95c83f24eef418bbda3a61375f128e5b0192e4f3f9b32"}, + {file = "aiohttp-3.14.3-cp310-cp310-win32.whl", hash = "sha256:a3e22975f905b89a55a488c2a08f2fdb2186175349e917d48985cc468a3d4c6e"}, + {file = "aiohttp-3.14.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdd0e2834dce1a26c1bbe26464861e16bbe217042cbff619247c11594472518c"}, + {file = "aiohttp-3.14.3-cp310-cp310-win_arm64.whl", hash = "sha256:eac645b09bcfdf73df7536331f0678c1086ea250981118ddb5199e17ccef72bb"}, + {file = "aiohttp-3.14.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e568e14940c09955aa51f4e645b6daa18a581c5dcfcd73744dcc86a856e3ced3"}, + {file = "aiohttp-3.14.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:54cfcdee2770dac994417cbb0ee1f3eb0e7cb6b30c79bf44f2c02ff79ec5124a"}, + {file = "aiohttp-3.14.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:21c016079415ed3fd676963e9793700a566d85dbbd6bfc564b9b2d209147dcc8"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d6088ec9894113802bddb3c09e974929aed2c7b3a8c456219b8aab4481f1a239"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:16ea7e24c309fb7c0bbd505d149abe4fe4dccfb8db911db7dbec0921bc889a6f"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56f355e79f71aef2a85c80305cc915f894b170dba76de5fe84f6351939b83c06"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:18c441d0a8fca6de8d1f546849b9f0ab20d435993e2c5b59562b2fae6be2f929"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53e7b4ce82b54a8bcc71b3b67a5cbd177ca1d7f592cbc92cd38b7349f73482db"}, + {file = "aiohttp-3.14.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f55119f7bf25f49ed210f6096090715da24f2943c62102448915fde3c62877ce"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9aa6e61fdf20105c4144e755bd586008ff450791d67b1c8146fdc15959c4d51c"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ccd4893707b3e2a13e39c90d43cf80edf2e4d0457935bcc103bf2346214c3f15"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2466434105a4e03113c36ec775cc2ebe6676b62eae326fa670bb607ef788c1c"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:ba59d59aba08ac02fc03b0c8983ccd5ee39a199d0552ce9e6d2b4845b34d59ae"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ed099d105449c4f9e84f24af203cd131349d4761d8813fa7e02c32e7128cd910"}, + {file = "aiohttp-3.14.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:152516815ef926786a0b6ae2b8f1fd2e0c71582dee0b435636865316fd4891b7"}, + {file = "aiohttp-3.14.3-cp311-cp311-win32.whl", hash = "sha256:a4af35c443e0b1a1bd6a8af3f3485d7fda15c142751a00f3ff8090f0b93346fa"}, + {file = "aiohttp-3.14.3-cp311-cp311-win_amd64.whl", hash = "sha256:e1e74298bab6ee0d6e749ed4fd1901c7e604bdda32c03d787a2cc71c46d0433d"}, + {file = "aiohttp-3.14.3-cp311-cp311-win_arm64.whl", hash = "sha256:03cd2bde3d7f085b64e549c985f4bb928cad7e8ecf5323bfca320db548d81b39"}, + {file = "aiohttp-3.14.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:39aded8c7f3b935b54aab1d8d73c70ec0ee2d3ec3b943e0e86611bc150ba47f5"}, + {file = "aiohttp-3.14.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5bcb6ff3fdab1258a192679ff1a05d44f59626430aa05cd1a9d2447423599228"}, + {file = "aiohttp-3.14.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:617105e2c3018ee38d0c8ce5ee3c84f621a6d8b9f723202aacaff28449ca91ee"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f631fe87a6f30df5fbe6d79640b25e4cffb38c31c7fb6f10871517b84b0f8c1a"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a94dbaae5ae27bd849c93570669bff91e0510f33a80805738e3de72a7be0447b"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8f2f1c4c032c7cedd7d8da6f54c97b70266c6570c3108d3fdffee7188bb70529"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ea05e1f97ceea523942d9b2a7d7c0359d781d683d6b043f5943a602b14da4787"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:543906c127fb1d929b95076db19b83fa2d46751006ff1e23b093aa5ac4d8db42"}, + {file = "aiohttp-3.14.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0a5ff2dfbb9ce645fa5b8ef3e02c6c0b9cc3f6030ff863d0c51fffc50cb5541b"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:041badb8f84396357c4d3ad26de6afd7a32b112f43d3c63045c0c8278cfd2043"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:530125ee1163c4219af35dc3aa1206e541e7b31b6efc1a3f93b70a136f65d427"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c8653fd547c93a61aadc612007790f5555cdd18946fa48cf45e26d8ea4ea473d"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:89176250f686cb9853c0fb7ead90e639e915b84a6f43eedc2a4e7ec21f1037f0"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3a26434dafe408229ff3403458ca58de24fb51936504decac49ce6755f77e59d"}, + {file = "aiohttp-3.14.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d1558173930a5a8d3069cee5c92fc91c87c4dbcb099debbb3622053717145a19"}, + {file = "aiohttp-3.14.3-cp312-cp312-win32.whl", hash = "sha256:16100ad3ab8d649fdfbee87602d9d2dcdca9df0b9eda8a1b5fdc0d41f96da559"}, + {file = "aiohttp-3.14.3-cp312-cp312-win_amd64.whl", hash = "sha256:33a2d7c28d33797a2e99923dffa63f83d908a19b6bf26cfe80fa790aa5e1a75a"}, + {file = "aiohttp-3.14.3-cp312-cp312-win_arm64.whl", hash = "sha256:362a3fd481769cac1a824514bcd86fda51c65e8fe6e051099e008fddde6db17c"}, + {file = "aiohttp-3.14.3-cp313-cp313-android_21_arm64_v8a.whl", hash = "sha256:2e9878ae68e4a5f1c0abe4dd497dbc3d51946f5837b56759e2a02e78fa90ef86"}, + {file = "aiohttp-3.14.3-cp313-cp313-android_21_x86_64.whl", hash = "sha256:f3d2669fe7dec7fc359ecdb5984b29b50d85d5d00f8c1cb61de4f4a24ee42627"}, + {file = "aiohttp-3.14.3-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:cc7cb243a68167172f48c1fd43cee91ec4b1d40cefd190edd43369d1a6bc9c82"}, + {file = "aiohttp-3.14.3-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:78253b573e6ffab5028924fc98bc281aae05445969982a10864bc360dea2016c"}, + {file = "aiohttp-3.14.3-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7041d52c3a7fa20c9e8c182b534704abb19502c8bdcbde7ab23bfda6f642394f"}, + {file = "aiohttp-3.14.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ac74facc01463f138b0da5580329cfcc82818dea5656e83ddcd11268fc12ff80"}, + {file = "aiohttp-3.14.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d6218d92e450824e9b4881f44e8c09f1853b490f9a64130801024a4793b1b3b0"}, + {file = "aiohttp-3.14.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:11fb37ef075669eee52ab1928fbf6e1741fada40409fa309ebde9607a962aebf"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55bdcc472aafe2de4a253045cc128007a64f1e0264fb675791e132ea5edaa3bd"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c39846c3aad97a8530c89d7a3869a8f8e9e3762c6ac0504481e5c80948f7e807"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5895ef58c4620afe02fa16044f023dc4dafec08158f9d08874a46a7dbc0341b8"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa9467a8113aa69d3d7c55a70ef0b7c636010a40993f3df9d9d0d73b3eb7ef24"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7d2deec16eeedf55f2c7cf75b521ea3856a5177e123844f8fd0f114ce252cb5"}, + {file = "aiohttp-3.14.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dd54d0e8717de95939766febac482ac0474d8ac3b048115f9f2b1d23a16e7db4"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:df82f3787c940c94986b34222d59c9e38843fba85139f36e85255a82ad5355a9"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:42a67efc36300d052fb4508a53e8b6901b9284b599ae63945c377569c5fcc1e1"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7a75aa63cbf9b21cfaf60dc2657e19df2c2867d91707d653fee171ffeedd1371"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e92eb8acc45eb6a9f4935071a77edf5b85cc6f8dfad5cd99e97653c26593cdde"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b014a6ed7cf912e787149fdc529166d3ceabac23f26efeea3158c9aba2354e7e"}, + {file = "aiohttp-3.14.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3d4f72af88ac2474bb5bca640030320e3d38a0163a1d7533500e87be458eef71"}, + {file = "aiohttp-3.14.3-cp313-cp313-win32.whl", hash = "sha256:5f08ec777f35ee70720233b8b9811d3bb5d728137f30ac91b7457709c3261ac0"}, + {file = "aiohttp-3.14.3-cp313-cp313-win_amd64.whl", hash = "sha256:dff9461ec275f22135650d5ba4b4931a11f3958df7dfbb8db630000d4dee0883"}, + {file = "aiohttp-3.14.3-cp313-cp313-win_arm64.whl", hash = "sha256:ddcac3c6b382e81f1dd0499199d4136b877beb4cb5ef770bbbfba56c4b8f55d2"}, + {file = "aiohttp-3.14.3-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:49f7325beb0f85ef4aef5f48f490269575f83e6e2acad00a1d80b807eb027062"}, + {file = "aiohttp-3.14.3-cp314-cp314-android_24_x86_64.whl", hash = "sha256:e3be98a7c30b8c25d573dafba7171d66dfb05ee6a9070fc46535464ff97700a6"}, + {file = "aiohttp-3.14.3-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:614c61d478b83953e261d02bb2df750f17227cd33ef8002945bf5aebbde21919"}, + {file = "aiohttp-3.14.3-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:1caa7b0d05f3e3a36f87788c59e970a7ee1cefcfcbb924a9f138c4a6551c9cb7"}, + {file = "aiohttp-3.14.3-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:dfa68deb2a443bdaa3ea5297b0699c1464f08aef3812b486d1348eee61b07dc0"}, + {file = "aiohttp-3.14.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:e72ee89e28d907a18f46959b4eb0bb06701cc7f8cf4366e00029e2ccfaaf5924"}, + {file = "aiohttp-3.14.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ad4c8b7488d745d2ca4838ebd8ae5ba9b56341d30b1da43640e4ce87f9f49646"}, + {file = "aiohttp-3.14.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:db332af25642007330fca8be5c4d194caf2bea7a7fc84415aff3497af5dfee6b"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25bd2708db6bdf6a6630dd37bdcdfcb47c4434d22ac69c64665b802910140b30"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:cef89a58e628c4efcac3275c2d68083f82426dcdc89c1492a6f654f9f7ea6ab9"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c23ec8ee9d5ab2f5421f9c7fffce208435607af27fd46d4a44e031954352838f"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e2667f0bbe7eb6c74eae5e9691441ad186e5845ca3cff63230fc09c4e7514f5d"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18cb43369747b2ae007bd2655fb8e63a099c2ff1d207962943636dac989b3147"}, + {file = "aiohttp-3.14.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d77640cc618c1d99fc4f8589c0f24a730adfa54eb1e57ef7bf0c8dfb78da898c"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:53e5179d8abb5710f8e83ba207c41c8d1261fcffd4616500e15ca2b7a33be10a"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:cd817772b2fcf2b8c0905795318485f9ec16eae60b29feb7f4c77085311637f0"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4e3ac92d90e92773b2362d506068e9a948192bd553e743c5b2429e28527c8661"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3f42e9b78301f11c8f861746175d8b9c1ccef713fcad9eab396e2f6db8ed4a22"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9d9edccfe496b476db5f398d97b865e9a6752bcf8aec4eef8390ce20fb64bb41"}, + {file = "aiohttp-3.14.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c5ec8fb1bcc31a8466f74aaf26c345d5c386fa4bd08a3f0eb9c7a4a3fe8b5bf"}, + {file = "aiohttp-3.14.3-cp314-cp314-win32.whl", hash = "sha256:38901a84da3ce22249f6e860bf8f90d141bcab7da090cc398f8bb58c0e44b7da"}, + {file = "aiohttp-3.14.3-cp314-cp314-win_amd64.whl", hash = "sha256:8b3b60de05f3dcb6f6a00f818bb2ec781cee4de0645f59ccaf99b1d1823b6100"}, + {file = "aiohttp-3.14.3-cp314-cp314-win_arm64.whl", hash = "sha256:1576145bdceeb92382d899751e12743a3a5b8e460a841e3e50543859e54864dc"}, + {file = "aiohttp-3.14.3-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:8800c996b01c2772a783e3e46f3e1abd5823029adca0df54231960de9bfefa5b"}, + {file = "aiohttp-3.14.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ebe8e504f058fe91223351cecd2d9d6946c9d241bb0250d898ffbdf584cc72b0"}, + {file = "aiohttp-3.14.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:30402d03a7c0ff52bce290b57e564e9079fd9d0cb545c8aba73f86a103162d2e"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fc7b5bfec6573f3ae844f457fdde5adeb713f8b8e4a81ad64fc207b49383716"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8a5fd34f7f7410d1730d5c2ba873cacb2eed3fede366feb268a70ba22581ed8f"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:270d3dace9ca2f10f0da5d8ebe519b7a310fc6112ed916e32df5866df0888553"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3ae5b3a59436d089b5395d910121a390feed4d00578eb95a0fd1a329fe963100"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2498f0fe69ead802f9675beca44a7c21c62fdaa4ec5145ea1c3ad6edbee29f85"}, + {file = "aiohttp-3.14.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a0dc483c00da8b673abbb367eb6f8d8f4bcec30eb58529ea13cb42e7fd2dfa33"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c7d3a97c678d34fc5b59da671ee9cd630096ddc643e7b5a30d54a2a6f3574d3f"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:f8fb78a83c9e5f741ca3a68cfb455c1f5bb83b4e7249a3848b3cd78d0a8563b0"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:74ab5b6a9fb13e873e5a90946588baecaf488745e1db1a4a5c433f971f035098"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:bd52f811e65f6fb634b1047159657c98f52b407f8efec907bcfc09da9a4c0a25"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:f0f177d1b195b9e06376cfd7d308d8a1b920909a609d03ac82a8c73bbb16d3b9"}, + {file = "aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:498c6c623134f8e09a3c4e60bcd607a0b4590dd7dbf08dd40851b27cbb520ccb"}, + {file = "aiohttp-3.14.3-cp314-cp314t-win32.whl", hash = "sha256:b304db572b4368edd8dda8a2274f73156fe15558fca4a917cb8a09fc47af5963"}, + {file = "aiohttp-3.14.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b20032766aedf6261c7a566585a40867d092ac03a0d81592d5370ef9b054f99b"}, + {file = "aiohttp-3.14.3-cp314-cp314t-win_arm64.whl", hash = "sha256:2e1161602f45a54de2ce0905243a95f58cb42dcd378402f3697f5e0b21e9d2e7"}, + {file = "aiohttp-3.14.3.tar.gz", hash = "sha256:9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc"}, ] [package.dependencies] @@ -188,29 +188,16 @@ files = [ [package.dependencies] vine = ">=5.0.0,<6.0.0" -[[package]] -name = "annotated-doc" -version = "0.0.4" -description = "Document parameters, class attributes, return types, and variables inline, with Annotated." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version < \"3.14\"" -files = [ - {file = "annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320"}, - {file = "annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4"}, -] - [[package]] name = "annotated-types" -version = "0.7.0" +version = "0.8.0" description = "Reusable constraint types to use with typing.Annotated" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, + {file = "annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0"}, + {file = "annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7"}, ] [[package]] @@ -245,14 +232,14 @@ webhooks = ["standardwebhooks (>=1.0.1,<2)"] [[package]] name = "anyio" -version = "4.13.0" +version = "4.14.2" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, - {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, + {file = "anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494"}, + {file = "anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f"}, ] [package.dependencies] @@ -264,58 +251,62 @@ trio = ["trio (>=0.32.0)"] [[package]] name = "asgiref" -version = "3.11.1" +version = "3.12.1" description = "ASGI specs, helper code, and adapters" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "asgiref-3.11.1-py3-none-any.whl", hash = "sha256:e8667a091e69529631969fd45dc268fa79b99c92c5fcdda727757e52146ec133"}, - {file = "asgiref-3.11.1.tar.gz", hash = "sha256:5f184dc43b7e763efe848065441eac62229c9f7b0475f41f80e207a114eda4ce"}, + {file = "asgiref-3.12.1-py3-none-any.whl", hash = "sha256:fe386d1c2bff7259ea95929266d12a8cf9a8b5a1c2598402967d8792e7a7c094"}, + {file = "asgiref-3.12.1.tar.gz", hash = "sha256:59dcb51c272ad209d59bed5708a64a333083e86017d7fcdd67498eeab7784340"}, ] [package.extras] -tests = ["mypy (>=1.14.0)", "pytest", "pytest-asyncio"] +mypy = ["mypy (>=1.14.0)"] +tests = ["pytest", "pytest-asyncio"] [[package]] name = "ast-serialize" -version = "0.4.0" +version = "0.6.0" description = "Python bindings for mypy AST serialization" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ast_serialize-0.4.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:a6f26937ce0293aafbece0e39019e020369a5a70486ff4088227f0cc888844a9"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:074032142777e3e6091977dc3c5146a8ca58ae6825b7f64e9a0b604153ddabd8"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:404f3462b4532e13a70b8849bba241dbd82e30043ff58d98c7e762fd925b116a"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:97c55336e16f5c4ca2bde7be94cca4b8f7d665d64f7008925a82e02707ba14ac"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:732b4ef76adcb0f298a7d18c4558336d83b1384f9ae0c7eaa1dc8d031b0a4390"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b3db87c4772097c0782250bcd550d66b1189a8c889793c7bcf153f4fee70005c"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43729a5e369ebbe7750635c0c206bc616fcd36e703cb9c4497d6b4df0291ee64"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:91d3786f3929786cdc4eeedfd110abb4603e7f6c1390c5af398f333a947b742d"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7fba7315fd4bd87cb5560792709f6e66e0606402d362c0a38dd32dfb66ba6066"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:4db9769d57deb5545ce56ebbbbe3436dcc0ae2688ce14c295cd14e106624ece7"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:dcd04f85a29deb80400e8987cfaceb9907140f763453cbffdbd6ff36f1b32c12"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:905fc11940831454d93589bd7ce2acb6a5eb01c2936156f751d2a21087c98cd3"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-win32.whl", hash = "sha256:3bdde2c4570143791f636aed4e3ef868f5b46eb90a18f8d5c41dd045aab08bef"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6551d55b8607b97a7755683d743200b398c61a0b71a11b7f00c89c335a11d0f4"}, - {file = "ast_serialize-0.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:7234ff086cb152ea2a3b7ef895b5ebeb6d80779df049d5c6431c8e3536d5b03c"}, - {file = "ast_serialize-0.4.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:dcded5056d9f3d201df7833082c07ebcbc566ffc3d4105c9fc9fe278fa086ecb"}, - {file = "ast_serialize-0.4.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:bd50d201098aae0d202805fe9606c0545492f69a3ec4403337e32c54ad29fc41"}, - {file = "ast_serialize-0.4.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6615b39cd747967c3aabe68bf3f5f26748e823cc6b474ddc1510ed188a824149"}, - {file = "ast_serialize-0.4.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91362c0a9fdf1c344b7f50a5b0508b11a0732102998fbd754a191f7187e77031"}, - {file = "ast_serialize-0.4.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:70d9c5d527bbfa69bd3c7d17dac11fb6781e36186a434a06d7d5892e0b2f88f9"}, - {file = "ast_serialize-0.4.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4738790cf54d8b416de992b87ee567056980bc82134d52458bd4985f389d1658"}, - {file = "ast_serialize-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:faa008dccfcb793ae9101325e4d6d026caaa5d845c2182f03749c759834b0a3a"}, - {file = "ast_serialize-0.4.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1c5245228e65d38cb48e1251f0ca71b0fa417e527141491e8c92f740e8e2d121"}, - {file = "ast_serialize-0.4.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8f5153e9c44a02e61f4042c5f9249d2e8a759773d621a0b2f445a899e536e181"}, - {file = "ast_serialize-0.4.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1e1fb90def261f6a0db885876f7e1a49ad2dbac38ad9f2f62dba2f9543af16e7"}, - {file = "ast_serialize-0.4.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf2ff7b654c8e95143e20f5d75878cbb78b65b928b26c4d58ef71cdba9d6d981"}, - {file = "ast_serialize-0.4.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:90fc5c0d35a22f1a92dd33635508626d50f8fc64deb897c23e78e666a60804c9"}, - {file = "ast_serialize-0.4.0-cp39-abi3-win32.whl", hash = "sha256:9ecd6a1fc1b86f1f4e8ae206759b6319c10019706b3496b01b54d02b9b2cd918"}, - {file = "ast_serialize-0.4.0-cp39-abi3-win_amd64.whl", hash = "sha256:79c8d015c771c8bfdb1208003b227b27c40034790a2c29c09f2317a041825ce2"}, - {file = "ast_serialize-0.4.0-cp39-abi3-win_arm64.whl", hash = "sha256:1026f565a7ab846337c630909089b3346a2fe417bf1552b1581ab01852137407"}, - {file = "ast_serialize-0.4.0.tar.gz", hash = "sha256:74e4e634ab82d1466acf0be27043178570b98ebeaa3165f9240a6fad4c286471"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:a7520b672827885bafeae7501f684d14d47d17e5f45256f9df547686cca52264"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a14191beec7e0c078d2fc1f6edc0aee88bcd4db9f18e1bc9f8052b559c22dddc"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32ef62ec34cf6be20ad77d4799556638fbdf187f3ae10698dfb20ef9f2c89516"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13b7769970a39983b0adf2f38917b1cd3b8946f76df045756c3d741bc689f089"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f7a408601bb3edaefb3bc67a4c01f5235e3253653b6a5729a2ee2382b35341c"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8670bfa51208a2c0c8d138928e40e998fab158f9200d53bb80c088b5b8eda7b8"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4826809eb8597a8cd59fd924b6d7c285b8969a1e0007e2cb652cab62376270f"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:577a6c189068686869f5f1ddc38363f3ae1808a4753b577266f9202071a7bb66"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:085de7f62dc9cc247eb01e965a362707d1d90b1d89a82c5bf78301a60a3c417b"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9f8a8b78b13173de6a9ec22111d9be674874cd5bdccda04f14ae5ebc2bef403a"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:f2ff3baffc3a29c1f15bc9098aa0c09763410262d5e6cef42116f7356c184554"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0067b25fce104eaae5b88383de9ab803faeb671831e14ca698b771b356e2600f"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c617417f9cbb0cb144f6283c3cbe0d2e0f01beaf9f608f662b21191058a626ec"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-win32.whl", hash = "sha256:5337cb256dcea3df9288205213d1601581536526b8f4da44b6974f1180f3252a"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2d947e45cafc4b09bd7528917fa84c517654a43de173c79785574b7b3068ac24"}, + {file = "ast_serialize-0.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6e15ec740436e1a0d62de848641abe5f3a2f89a7f94907d534795ac91bbacf14"}, + {file = "ast_serialize-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:093cb8bb91b720d8523580498d031791bb1bbaa048599c3d21085d380e11a596"}, + {file = "ast_serialize-0.6.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:e61580a69faf47e3689795367ed211f2a10fd741478cc0f36a0f128793360aad"}, + {file = "ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:305802f2ce2a7c4e87835078ea85c58b586ddda8095b92fe2ead9364ae19c80a"}, + {file = "ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7b8b8f0c42f752ea00b2b7d7c090b3f80d9c1c5c75cadf16423790a0cc74081"}, + {file = "ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd5b91b9e6f2356ace3a556963b0cd783b395fbbb0bb17b4defc283415466e77"}, + {file = "ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d6ef91590258ada18909b9caea344dac4de2013906b035473cd674a43f4b790"}, + {file = "ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcbed41e9386059fc0261d602445ede0976c2ecec2939688bcbcb9ed0b6f28b7"}, + {file = "ast_serialize-0.6.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:cdc4e6f930b9090c2f92c9036ad12ffb8e6e44d4a5ba06f1458a05d60f203f7b"}, + {file = "ast_serialize-0.6.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:897ac47b5637be41c0c07061c8a912fafa967ef1dc73fa115e4bfa70882a093b"}, + {file = "ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c4af9a1386166e40ed01464991806f89038a2d89782576c7774876fa77034e32"}, + {file = "ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:c901adbd750029b9ac4ad3d6aa56853e0ad4875119fbf52b7b8298afc223828b"}, + {file = "ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3ae22a366b752ab4496191525b78b097b5b72d531752e3c1dd7e383a8f2c8a1a"}, + {file = "ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4ed29121da8b3fdc291002801a1de0f76248fa07dce89157a5f277842cf6126e"}, + {file = "ast_serialize-0.6.0-cp39-abi3-pyemscripten_2026_0_wasm32.whl", hash = "sha256:b1dac4e09d341c1300ba69cdcbe62867b32a8c75d90db9bf4d083bec3b039f0b"}, + {file = "ast_serialize-0.6.0-cp39-abi3-win32.whl", hash = "sha256:82c312a7844d2fdeb4d5c48bd3d215bf940dafd4704e1a9bcf252a99010a99b1"}, + {file = "ast_serialize-0.6.0-cp39-abi3-win_amd64.whl", hash = "sha256:113b58346f9ceb664352032770caca817d4a3c86f611c6088e6ef65ddaa70f0e"}, + {file = "ast_serialize-0.6.0-cp39-abi3-win_arm64.whl", hash = "sha256:ccd132fe8db56f61fe743b1f644d01b8d65b83248a8da506f3132bda86d6ed5e"}, + {file = "ast_serialize-0.6.0.tar.gz", hash = "sha256:aadd3ffcf4858c9726bf3515f7b199c7eadbe504f96028e4a87172c0da65a8fe"}, ] [[package]] @@ -374,14 +365,14 @@ pycodestyle = ">=2.12.0" [[package]] name = "beautifulsoup4" -version = "4.14.3" +version = "4.15.0" description = "Screen-scraping library" optional = false python-versions = ">=3.7.0" groups = ["main"] files = [ - {file = "beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb"}, - {file = "beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86"}, + {file = "beautifulsoup4-4.15.0-py3-none-any.whl", hash = "sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9"}, + {file = "beautifulsoup4-4.15.0.tar.gz", hash = "sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7"}, ] [package.dependencies] @@ -472,14 +463,14 @@ files = [ [[package]] name = "cachetools" -version = "7.1.4" +version = "7.1.6" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "cachetools-7.1.4-py3-none-any.whl", hash = "sha256:323dc4127934744db5b54eb4924482d7edafbf9554e820d1531c2e08c0e4ef54"}, - {file = "cachetools-7.1.4.tar.gz", hash = "sha256:437f55a4e0c1b01a4f3077cc470e6991d47430970e36fbcb77e2be0df4fc1cd6"}, + {file = "cachetools-7.1.6-py3-none-any.whl", hash = "sha256:2c12e255780330af28b91bb7fb96cce4c766f04e38396b9a24510190a5827096"}, + {file = "cachetools-7.1.6.tar.gz", hash = "sha256:c7a79e7f30ba9943c1cefd08cc36f006aaae086e017af9166f1d59d6170c47e1"}, ] [[package]] @@ -542,108 +533,124 @@ zstd = ["zstandard (==0.23.0)"] [[package]] name = "certifi" -version = "2026.6.17" +version = "2026.7.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["main", "dev"] files = [ - {file = "certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"}, - {file = "certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432"}, + {file = "certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775"}, + {file = "certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55"}, ] [[package]] name = "cffi" -version = "2.0.0" +version = "2.1.0" description = "Foreign Function Interface for Python calling C code." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, - {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4"}, - {file = "cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5"}, - {file = "cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb"}, - {file = "cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a"}, - {file = "cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739"}, - {file = "cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe"}, - {file = "cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664"}, - {file = "cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414"}, - {file = "cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743"}, - {file = "cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5"}, - {file = "cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5"}, - {file = "cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d"}, - {file = "cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d"}, - {file = "cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037"}, - {file = "cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba"}, - {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94"}, - {file = "cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187"}, - {file = "cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18"}, - {file = "cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5"}, - {file = "cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6"}, - {file = "cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb"}, - {file = "cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3"}, - {file = "cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26"}, - {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c"}, - {file = "cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b"}, - {file = "cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27"}, - {file = "cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75"}, - {file = "cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91"}, - {file = "cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5"}, - {file = "cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef"}, - {file = "cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775"}, - {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205"}, - {file = "cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1"}, - {file = "cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f"}, - {file = "cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25"}, - {file = "cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad"}, - {file = "cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9"}, - {file = "cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc"}, - {file = "cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592"}, - {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512"}, - {file = "cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4"}, - {file = "cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e"}, - {file = "cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6"}, - {file = "cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9"}, - {file = "cffi-2.0.0-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf"}, - {file = "cffi-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f"}, - {file = "cffi-2.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65"}, - {file = "cffi-2.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322"}, - {file = "cffi-2.0.0-cp39-cp39-win32.whl", hash = "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a"}, - {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, - {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, + {file = "cffi-2.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:b65f590ef2a44640f9a05dbb548a429b4ade77913ce683ac8b1480777658a6c0"}, + {file = "cffi-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164bff1657b2a74f0b6d54e11c9b375bc97b931f2ca9c43fcf875838da1570dd"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:c941bb58d5a6e1c3892d86e42927ed6c180302f07e6d395d08c416e594b98b46"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a016194dbe13d14ee9556e734b772d8d67b947092b268d757fd4290e3ba2dfc2"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19c54ac121cad98450b4896fa9a43ee0180d57bc4bc911a33db6cab1efab6cd3"}, + {file = "cffi-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d433a51f1870e43a13b6732f92aaf540ff77c2015097c78556f75a2d6c030e0"}, + {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3d7f118b5adbfdfead90c25822690b02bc8074fba949bb7858bec4ebd55adb43"}, + {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c5f5df567f6eb216de69be06ce55c8b714090fae02b18a3b40da8163b8c5fa9c"}, + {file = "cffi-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:11b3fb55f4f8ad92274ed26705f65d8f91457de71f5380061eb6d125a768fecd"}, + {file = "cffi-2.1.0-cp310-cp310-win32.whl", hash = "sha256:9d72af0cf10a76a600a9690078fe31c63b9588c8e86bf9fd353f713c84b5db0f"}, + {file = "cffi-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da"}, + {file = "cffi-2.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc"}, + {file = "cffi-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f"}, + {file = "cffi-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565"}, + {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c"}, + {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02"}, + {file = "cffi-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e"}, + {file = "cffi-2.1.0-cp311-cp311-win32.whl", hash = "sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479"}, + {file = "cffi-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458"}, + {file = "cffi-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d"}, + {file = "cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f"}, + {file = "cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7"}, + {file = "cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66"}, + {file = "cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe"}, + {file = "cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b"}, + {file = "cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a"}, + {file = "cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384"}, + {file = "cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6"}, + {file = "cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda"}, + {file = "cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b"}, + {file = "cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a"}, + {file = "cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0"}, + {file = "cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224"}, + {file = "cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c"}, + {file = "cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a"}, + {file = "cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2"}, + {file = "cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512"}, + {file = "cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f"}, + {file = "cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a"}, + {file = "cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3"}, + {file = "cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d"}, + {file = "cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac"}, + {file = "cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6"}, + {file = "cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913"}, + {file = "cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d"}, + {file = "cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5"}, + {file = "cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce"}, + {file = "cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326"}, + {file = "cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd"}, + {file = "cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb"}, + {file = "cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804"}, + {file = "cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714"}, + {file = "cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376"}, + {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98"}, + {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13"}, + {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d"}, + {file = "cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056"}, + {file = "cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4"}, + {file = "cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94"}, + {file = "cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76"}, + {file = "cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5"}, + {file = "cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8"}, + {file = "cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c"}, + {file = "cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001"}, + {file = "cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3"}, + {file = "cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc"}, + {file = "cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699"}, + {file = "cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022"}, + {file = "cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0"}, + {file = "cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1"}, + {file = "cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28"}, + {file = "cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629"}, + {file = "cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6"}, + {file = "cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853"}, + {file = "cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda"}, + {file = "cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc"}, + {file = "cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca"}, + {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d"}, + {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8"}, + {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd"}, + {file = "cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f"}, + {file = "cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc"}, + {file = "cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9"}, + {file = "cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b"}, + {file = "cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5"}, + {file = "cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210"}, + {file = "cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9"}, ] markers = {main = "os_name == \"nt\" and implementation_name != \"pypy\" or platform_python_implementation != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\""} @@ -707,153 +714,117 @@ tests = ["async-timeout", "cryptography (>=1.3.0)", "pytest", "pytest-asyncio", [[package]] name = "charset-normalizer" -version = "3.4.7" +version = "3.4.9" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" groups = ["main", "dev"] files = [ - {file = "charset_normalizer-3.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win32.whl", hash = "sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943"}, - {file = "charset_normalizer-3.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win32.whl", hash = "sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00"}, - {file = "charset_normalizer-3.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win32.whl", hash = "sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6"}, - {file = "charset_normalizer-3.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win32.whl", hash = "sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110"}, - {file = "charset_normalizer-3.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f"}, - {file = "charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c"}, - {file = "charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e5f4d355f0a2b1a31bc3edec6795b46324349c9cb25eed068049e4f472fb4259"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:16d971e29578a5e97d7117866d15889a4a07befe0e87e703ed63cd90cb348c01"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dca4bbc466a95ba9c0234ef56d7dd9509f63da22274589ebd4ed7f1f4d4c54e3"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e80c8378d8f3d83cd3164da1ad2df9e37a666cdde7b1cb2298ed0b558064be30"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:36836d6ff945a00b88ba1e4572d721e60b5b8c98c155d465f56ad19d68f23734"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_armv7l.whl", hash = "sha256:bd9b23791fe793e4968dba0c447e12f78e425c59fc0e3b97f6450f4781f3ee60"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:aef65cd602a6d0e0ff6f9930fcb1c8fec60dd2cfcb6facaf4bdb0e5873042db0"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:82b271f5137d07749f7bf32f70b17ab6eaabedd297e75dce75081a24f76eb545"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:1efde3cae86c8c273f1eb3b287be7d8499420cf2fe7585c41d370d3e790054a5"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:c593052c465475e64bbfe5dbd81680f64a67fdc752c56d7a0ae205dc8aeefe0f"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:af21eb4409a119e365397b2adbaca4c9ccab56543a65d5dbd9f920d6ac29f686"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:84c018e49c3bf790f9c2771c45e9313a08c2c2a6342b162cd650258b57817706"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dd915403e231e6b1809fe9b6d9fc55cf8fb5e02765ac625d9cd623342a7905d7"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-win32.whl", hash = "sha256:320ade88cfb846b8cd6b4ddf5ee9e80ee0c1f52401f2456b84ae1ae6a1a5f207"}, - {file = "charset_normalizer-3.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:1dc8b0ea451d6e69735094606991f32867807881400f808a106ee1d963c46a83"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:177a0ba5f0211d488e295aaf82707237e331c24788d8d76c96c5a41594723217"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e0d51f618228538a3e8f46bd246f87a6cd030565e015803691603f55e12afb5"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:14265bfe1f09498b9d8ec91e9ec9fa52775edf90fcbde092b25f4a33d444fea9"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:87fad7d9ba98c86bcb41b2dc8dbb326619be2562af1f8ff50776a39e55721c5a"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f22dec1690b584cea26fade98b2435c132c1b5f68e39f5a0b7627cd7ae31f1dc"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:d61f00a0869d77422d9b2aba989e2d24afa6ffd552af442e0e58de4f35ea6d00"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6370e8686f662e6a3941ee48ed4742317cafbe5707e36406e9df792cdb535776"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a6c5863edfbe888d9eff9c8b8087354e27618d9da76425c119293f11712a6319"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ed065083d0898c9d5b4bbec7b026fd755ff7454e6e8b73a67f8c744b13986e24"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2cd4a60d0e2fb04537162c62bbbb4182f53541fe0ede35cdf270a1c1e723cc42"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:813c0e0132266c08eb87469a642cb30aaff57c5f426255419572aaeceeaa7bf4"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:07d9e39b01743c3717745f4c530a6349eadbfa043c7577eef86c502c15df2c67"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c0f081d69a6e58272819b70288d3221a6ee64b98df852631c80f293514d3b274"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win32.whl", hash = "sha256:8751d2787c9131302398b11e6c8068053dcb55d5a8964e114b6e196cf16cb366"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:12a6fff75f6bc66711b73a2f0addfc4c8c15a20e805146a02d147a318962c444"}, - {file = "charset_normalizer-3.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:bb8cc7534f51d9a017b93e3e85b260924f909601c3df002bcdb58ddb4dc41a5c"}, - {file = "charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d"}, - {file = "charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd6280cf040f233bd7d3407b743b4b4c74f70e8e1c4199cb112a62c941c0772a"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa99adc8f081b475a12843953db36831eaf83ec33eb46a90629ca6a5de45a616"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c1225416b463483160e4af85d5fc3a9690ccb53fd4b1865a6437825f5ede3209"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:16d10d789dd9bcca1173c95af82c58433122564b7bc39385124be735a35cbe99"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bb41182d93ea91f60b4bc8fbf4c820c69ef8a12ab2d917f3f1834f1acad07e8"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:bcf74c1df76758a395bf0af608c04c82257523f55c9868b334f06270d0f2112b"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b5314963fce9b0b12743891de876e724997864ee22aa496f903f426c7e2fa5b2"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e9701d0049d92c16703a42771b98d560b95248949f23f8cf7b4eddd201814fb9"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:65a7ff3f705e57d392f7261b6d0550fe137c3019477431f1c355e0db0a7d3e15"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79580094b00d1789d1f93ea55bc43cb2f611910c72235b7657f3482ddcc1b22d"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-win32.whl", hash = "sha256:432786d3561e69aeeae6c7e8648964ce0ad05736120135601f87ac26b9c83381"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:8c041122946b7ba21bb32c45b1aa57b1be35527690aeb3c5c234521085632eee"}, + {file = "charset_normalizer-3.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:375b83ed0aecfce76c16d198fbc21f3b11b337d68662bea0a995046682a11419"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e94703ec9684807f20cfb5eed95c70f67f2a8f21ad620146d7b5a13677b93e5"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a441ea71902098ffe78c5abe6c494f44160b4af614ed16c3d9a3b1d17fd8ee2"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:304b13570067b2547562e308af560b3963857b1fa90bd6afd978130130fe2d6a"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4773092f8019072343a7447203308b176e10199920eb02d6195e81bbb3274c29"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:04ce310cb89c15df659582aee80a0603788732a5e017d5bd5c81158106ce249c"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:c0323c9daef75ef2e5083624b4585018a0c9d5e3b40f607eed81a311270b934b"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:871ff67ea1aad4dfd91736464934d56b32dac49f9fbe16cddba36198a7b3a0db"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:67830fc78e67501f47bb950471b2dcb9b35b140084429318e862895a8e89c993"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:3d92613ec25e43b05f042302531ec0f00b8445190e43325880cbd6ab7c2581da"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:280081916dc341820640489a66e4696049401ef1cf6dd672f672e70ad915aca3"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-win32.whl", hash = "sha256:ac351b3b8014eead140e77e9717e2992c6bbe30b63bc3422422eb84865412e3d"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:6366a16e1a25018694d6a5d784d09b046edc9eac40ea2b54065c3052672516a1"}, + {file = "charset_normalizer-3.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:1d22856ffbe153a602df38e4a5464f0b748a54002e0d69ac6d2ad0a197cc99ec"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-win32.whl", hash = "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0"}, + {file = "charset_normalizer-3.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-win32.whl", hash = "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115"}, + {file = "charset_normalizer-3.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-win32.whl", hash = "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b"}, + {file = "charset_normalizer-3.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-win32.whl", hash = "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177"}, + {file = "charset_normalizer-3.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:253a4a220747e8b5faf57ec320c4f5efb0cef05f647420bf267143ec15dba10a"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:68ce9f4d6b26d5ccbf7fd4459bf75f74a0a146677ebba80597df60cbdb20e6f4"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:58150c9f9b9a552505912d182ccdf26f6396fb6094816ceebcbb20eecabaed94"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df7276909358e5635ae203673ab7e509ddd224225a8d6b0790bf13eb2bde1cc5"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c09a49d6cde137258beb3d551994a2927fd35ad5cf96aed573f61bbd67c5f84"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:231ddcbb35e2ff8973e1365db41fe0572662893b99a05deb183b68ad4c0c8bd4"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:920079c3f7456fa213e0829ed2073aaa727fd39d889ead5b4f35d0de5460d04f"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0fa1aec2d32bcc03c8fa0f6f1712caad1adc38509f31142112e5c9daf5b9c833"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:ad41ba96094304aa090f5a30cb6e4fb3b3f1c264c523394b4c39bbacc4dc92ba"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:43b9e366a31fdd1c87d0eb08f579b4a82b723ea54338f040d6b4e518a026ea29"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-win32.whl", hash = "sha256:93d59d504b230e83c7a843251681959a0b6a9cd76f6e146ce1b8a80eb8739af9"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-win_amd64.whl", hash = "sha256:ddf4af30b417d9fe16481e9b81c27ab2a7cde1ff7ba3e85653b02db7d145dc7b"}, + {file = "charset_normalizer-3.4.9-cp39-cp39-win_arm64.whl", hash = "sha256:476743fe6dfe14a2da12e3ac79125dc84a3b2cf8094369a47a1529b0cd8549fe"}, + {file = "charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5"}, + {file = "charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b"}, ] [[package]] name = "click" -version = "8.3.3" +version = "8.4.2" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "click-8.3.3-py3-none-any.whl", hash = "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613"}, - {file = "click-8.3.3.tar.gz", hash = "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2"}, + {file = "click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76"}, + {file = "click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6"}, ] [package.dependencies] @@ -1129,42 +1100,42 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "debugpy" -version = "1.8.20" +version = "1.8.21" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "debugpy-1.8.20-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:157e96ffb7f80b3ad36d808646198c90acb46fdcfd8bb1999838f0b6f2b59c64"}, - {file = "debugpy-1.8.20-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:c1178ae571aff42e61801a38b007af504ec8e05fde1c5c12e5a7efef21009642"}, - {file = "debugpy-1.8.20-cp310-cp310-win32.whl", hash = "sha256:c29dd9d656c0fbd77906a6e6a82ae4881514aa3294b94c903ff99303e789b4a2"}, - {file = "debugpy-1.8.20-cp310-cp310-win_amd64.whl", hash = "sha256:3ca85463f63b5dd0aa7aaa933d97cbc47c174896dcae8431695872969f981893"}, - {file = "debugpy-1.8.20-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:eada6042ad88fa1571b74bd5402ee8b86eded7a8f7b827849761700aff171f1b"}, - {file = "debugpy-1.8.20-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:7de0b7dfeedc504421032afba845ae2a7bcc32ddfb07dae2c3ca5442f821c344"}, - {file = "debugpy-1.8.20-cp311-cp311-win32.whl", hash = "sha256:773e839380cf459caf73cc533ea45ec2737a5cc184cf1b3b796cd4fd98504fec"}, - {file = "debugpy-1.8.20-cp311-cp311-win_amd64.whl", hash = "sha256:1f7650546e0eded1902d0f6af28f787fa1f1dbdbc97ddabaf1cd963a405930cb"}, - {file = "debugpy-1.8.20-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:4ae3135e2089905a916909ef31922b2d733d756f66d87345b3e5e52b7a55f13d"}, - {file = "debugpy-1.8.20-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:88f47850a4284b88bd2bfee1f26132147d5d504e4e86c22485dfa44b97e19b4b"}, - {file = "debugpy-1.8.20-cp312-cp312-win32.whl", hash = "sha256:4057ac68f892064e5f98209ab582abfee3b543fb55d2e87610ddc133a954d390"}, - {file = "debugpy-1.8.20-cp312-cp312-win_amd64.whl", hash = "sha256:a1a8f851e7cf171330679ef6997e9c579ef6dd33c9098458bd9986a0f4ca52e3"}, - {file = "debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a"}, - {file = "debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf"}, - {file = "debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393"}, - {file = "debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7"}, - {file = "debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173"}, - {file = "debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad"}, - {file = "debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f"}, - {file = "debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be"}, - {file = "debugpy-1.8.20-cp38-cp38-macosx_15_0_x86_64.whl", hash = "sha256:b773eb026a043e4d9c76265742bc846f2f347da7e27edf7fe97716ea19d6bfc5"}, - {file = "debugpy-1.8.20-cp38-cp38-manylinux_2_34_x86_64.whl", hash = "sha256:20d6e64ea177ab6732bffd3ce8fc6fb8879c60484ce14c3b3fe183b1761459ca"}, - {file = "debugpy-1.8.20-cp38-cp38-win32.whl", hash = "sha256:0dfd9adb4b3c7005e9c33df430bcdd4e4ebba70be533e0066e3a34d210041b66"}, - {file = "debugpy-1.8.20-cp38-cp38-win_amd64.whl", hash = "sha256:60f89411a6c6afb89f18e72e9091c3dfbcfe3edc1066b2043a1f80a3bbb3e11f"}, - {file = "debugpy-1.8.20-cp39-cp39-macosx_15_0_x86_64.whl", hash = "sha256:bff8990f040dacb4c314864da95f7168c5a58a30a66e0eea0fb85e2586a92cd6"}, - {file = "debugpy-1.8.20-cp39-cp39-manylinux_2_34_x86_64.whl", hash = "sha256:70ad9ae09b98ac307b82c16c151d27ee9d68ae007a2e7843ba621b5ce65333b5"}, - {file = "debugpy-1.8.20-cp39-cp39-win32.whl", hash = "sha256:9eeed9f953f9a23850c85d440bf51e3c56ed5d25f8560eeb29add815bd32f7ee"}, - {file = "debugpy-1.8.20-cp39-cp39-win_amd64.whl", hash = "sha256:760813b4fff517c75bfe7923033c107104e76acfef7bda011ffea8736e9a66f8"}, - {file = "debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7"}, - {file = "debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33"}, + {file = "debugpy-1.8.21-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:8eeab7b5462f683452c57c0126aaa5ec4e974ddb705f39ba87dff8818c8e08f9"}, + {file = "debugpy-1.8.21-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:0fddfdc130ac6d8bfc0415b0409822fa901c8f310e5c945ac5653a0352532344"}, + {file = "debugpy-1.8.21-cp310-cp310-win32.whl", hash = "sha256:72b5d676c4cbfac3bac5bb01c138a4656e843f93f03ce2a5f4e394ad49fbee73"}, + {file = "debugpy-1.8.21-cp310-cp310-win_amd64.whl", hash = "sha256:a7fe47fd23da57b9e0bec3f4a8ee65a2dc55782455ed7f2141d75ab5d2eaeef5"}, + {file = "debugpy-1.8.21-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:da456226c7b4c69e35dbe35dcee6623d912000a77816db7856a41af1c72a0264"}, + {file = "debugpy-1.8.21-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:f68b891688e61bdc08b8d364d919ff0051e0b94657b39dcd027bc3173edb7cdc"}, + {file = "debugpy-1.8.21-cp311-cp311-win32.whl", hash = "sha256:f843a8b08c2edeaf9b1582eed4f25441af21a297c22ff16bf76a662557aa9c9e"}, + {file = "debugpy-1.8.21-cp311-cp311-win_amd64.whl", hash = "sha256:84c564d8cc701d41843b29a92814c1f1bef6798724ca9d675c284ad9f6a547d7"}, + {file = "debugpy-1.8.21-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:9f96713896f39c3dff0ee841f47320c3f2983d33c341e009361bb0ebc79adc4e"}, + {file = "debugpy-1.8.21-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:c193d474f0a211191f2b4449d2d06157c689013035bd952f3b617e0ef422b176"}, + {file = "debugpy-1.8.21-cp312-cp312-win32.whl", hash = "sha256:4743373c1cac7f9e74a1b9915bf1dbe0e900eca657ffb170ae07ac8363205ae9"}, + {file = "debugpy-1.8.21-cp312-cp312-win_amd64.whl", hash = "sha256:bd7ba9dd3daa7c2f942c6ca8d4695a16bf9ac16b63615261c7982bc74f7ed20c"}, + {file = "debugpy-1.8.21-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:13678151fc401e2d68c9880b91e28714f797d40422994572b24560ef80910a88"}, + {file = "debugpy-1.8.21-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:ecbd158386c31ffe71d46f72d44d56e66331ab9b16cad649156d514368f23ab2"}, + {file = "debugpy-1.8.21-cp313-cp313-win32.whl", hash = "sha256:2c2ae706dec41d99a9ca1f7ebc987a83e65578363be6f6b3ac9067504917fae1"}, + {file = "debugpy-1.8.21-cp313-cp313-win_amd64.whl", hash = "sha256:aa648733047443eb1d07682c4ef287d36a54507b643ffdf38b09a3ef002c72a0"}, + {file = "debugpy-1.8.21-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9bb2a685287a2ac9b181cde89edcec64845cb51de7faaa75badb9a698bc24782"}, + {file = "debugpy-1.8.21-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:3d6922439bf33fd38a3e2c447869ebc7b97da5cd3d329ff1ef9bc06c4903437e"}, + {file = "debugpy-1.8.21-cp314-cp314-win32.whl", hash = "sha256:15d4963bd5ffa48f0da0947fd06757fa7621945048a14ad7705431566d3c0e7c"}, + {file = "debugpy-1.8.21-cp314-cp314-win_amd64.whl", hash = "sha256:fe0744a12353406de0ae8ccff0d0a4a666f00801a3db8fd04e7a5f761cd520e8"}, + {file = "debugpy-1.8.21-cp38-cp38-macosx_15_0_x86_64.whl", hash = "sha256:0042da0ecd0a8b50dc4a54395ecd870d258d73fa18776f50c91fdcabdcad2675"}, + {file = "debugpy-1.8.21-cp38-cp38-manylinux_2_34_x86_64.whl", hash = "sha256:ffd932c6796afadab6993ec96745918a8cb2444dbd392074f769db5ea40ab440"}, + {file = "debugpy-1.8.21-cp38-cp38-win32.whl", hash = "sha256:4e7c2d784d78ad4b71a5f8cd7b59c167719ec8a7a0211dbb3eb1bfeda78bc4e2"}, + {file = "debugpy-1.8.21-cp38-cp38-win_amd64.whl", hash = "sha256:aa9d941d6dfe3d0407e4b3ca0b9ec466030e260fbf1174094f68785680f66db6"}, + {file = "debugpy-1.8.21-cp39-cp39-macosx_15_0_x86_64.whl", hash = "sha256:9f5171176a0084b95d2ebe55a4d1f7b2a75b74c5dbec577ebd3a85c740551c36"}, + {file = "debugpy-1.8.21-cp39-cp39-manylinux_2_34_x86_64.whl", hash = "sha256:f15c10084f9861b5e8414a48f18f8e4aadf51a98a59e72c16aa28281ca994672"}, + {file = "debugpy-1.8.21-cp39-cp39-win32.whl", hash = "sha256:4e70cc8b5079f885cb43910924ee0aab73b8b6b2a14eff23afdd9895d86e79eb"}, + {file = "debugpy-1.8.21-cp39-cp39-win_amd64.whl", hash = "sha256:e935f9dc0501be523c8a8e1853c39432e1354e9ece717ae5998fd2371c4542c3"}, + {file = "debugpy-1.8.21-py2.py3-none-any.whl", hash = "sha256:b1e37d333663c8851516a47364ef473da127f9caebe4417e6df6f5825a7e9a92"}, + {file = "debugpy-1.8.21.tar.gz", hash = "sha256:a3c53278e84c94e11bd87c53970ec391d1a67396c8b22609fcac576520e611a6"}, ] [[package]] @@ -1218,14 +1189,14 @@ profile = ["gprof2dot (>=2022.7.29)"] [[package]] name = "distlib" -version = "0.4.0" +version = "0.4.3" description = "Distribution utilities" optional = false python-versions = "*" groups = ["main", "dev"] files = [ - {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, - {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, + {file = "distlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b"}, + {file = "distlib-0.4.3.tar.gz", hash = "sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed"}, ] [[package]] @@ -1370,18 +1341,18 @@ uritemplate = ">=4.1.1,<5.0.0" [[package]] name = "django-simple-history" -version = "3.11.0" +version = "3.13.0" description = "Store model history and view/revert changes from admin site." optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "django_simple_history-3.11.0-py3-none-any.whl", hash = "sha256:f3c298db49e418ffce7fb709a5e83108452ea2179ec5c4b9232484c25427192a"}, - {file = "django_simple_history-3.11.0.tar.gz", hash = "sha256:2c587479cf2c3071e9aa555d0d11b73676994db4910770958f57659ade2deffe"}, + {file = "django_simple_history-3.13.0-py3-none-any.whl", hash = "sha256:1cf1d83054479f64aee022023afc1671843aa0a99888799c5c4c3966b0252521"}, + {file = "django_simple_history-3.13.0.tar.gz", hash = "sha256:ca3c1e4ccd5f16f45fbbef6015ee2a246465fd9bd924100df8e9dfb368c4f26c"}, ] [package.dependencies] -django = ">=4.2" +django = ">=5.2" [[package]] name = "django-solo" @@ -1400,14 +1371,14 @@ django = ">=4.2" [[package]] name = "django-stubs" -version = "6.0.3" +version = "6.0.7" description = "Mypy stubs for Django" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "django_stubs-6.0.3-py3-none-any.whl", hash = "sha256:5fee22bcbbad59a78c727a820b6f4e68ff442ca76a922b7002e57c25dd7cb390"}, - {file = "django_stubs-6.0.3.tar.gz", hash = "sha256:ee895f403c373608eeb50822f0733f9d9ec5ab12731d4ab58956053bb95fdd9e"}, + {file = "django_stubs-6.0.7-py3-none-any.whl", hash = "sha256:7ed9a14c438e589272ca04e966dee82a4d1ff7ca5c2171bc986c50a0d03ec35b"}, + {file = "django_stubs-6.0.7.tar.gz", hash = "sha256:bc55431c0af745a64e39cf33a8d36c87dccbedeae2fe26fab47dd355270e8538"}, ] [package.dependencies] @@ -1417,20 +1388,20 @@ types-pyyaml = "*" typing-extensions = ">=4.11.0" [package.extras] -compatible-mypy = ["mypy (>=1.13,<1.21)"] +compatible-mypy = ["mypy (>=1.13,<2.4)"] oracle = ["oracledb"] redis = ["redis", "types-redis"] [[package]] name = "django-stubs-ext" -version = "6.0.3" +version = "6.0.7" description = "Monkey-patching and extensions for django-stubs" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "django_stubs_ext-6.0.3-py3-none-any.whl", hash = "sha256:9e4105955419ae310d7da9cfd808e039d4dae3092c628f021057bb4f2c237f8f"}, - {file = "django_stubs_ext-6.0.3.tar.gz", hash = "sha256:3307d42132bc295d5744de6276bc5fdf6896efc70f891e21c0ae8bdf529d2762"}, + {file = "django_stubs_ext-6.0.7-py3-none-any.whl", hash = "sha256:53a9c7c5a7c7e718cc6308cfce1e7470f2cac0b9d38dbcd60fbfa82704f1d592"}, + {file = "django_stubs_ext-6.0.7.tar.gz", hash = "sha256:c3172c5126614fd2a44d0196b313b44c21f717cb09477ba52b447d41f4ce613e"}, ] [package.dependencies] @@ -1439,18 +1410,18 @@ typing-extensions = "*" [[package]] name = "django-timezone-field" -version = "7.2.1" +version = "7.2.2" description = "A Django app providing DB, form, and REST framework fields for zoneinfo and pytz timezone objects." optional = false python-versions = "<4.0,>=3.8" groups = ["main"] files = [ - {file = "django_timezone_field-7.2.1-py3-none-any.whl", hash = "sha256:276915b72c5816f57c3baf9e43f816c695ef940d1b21f91ebf6203c09bf4ad44"}, - {file = "django_timezone_field-7.2.1.tar.gz", hash = "sha256:def846f9e7200b7b8f2a28fcce2b78fb2d470f6a9f272b07c4e014f6ba4c6d2e"}, + {file = "django_timezone_field-7.2.2-py3-none-any.whl", hash = "sha256:30354d0f37462a0b9b5c289e271580a6be9b58dea30e7bf88435372882c8fa7a"}, + {file = "django_timezone_field-7.2.2.tar.gz", hash = "sha256:a004d0b19fe10bf5964cb21a65b36324b16a61879e4711c0dafdf8d6253e8ebc"}, ] [package.dependencies] -Django = ">=3.2,<6.1" +Django = ">=4.2,<6.2" [[package]] name = "djangorestframework" @@ -1494,23 +1465,23 @@ test = ["cryptography", "freezegun", "pytest", "pytest-cov", "pytest-django", "p [[package]] name = "djangorestframework-stubs" -version = "3.16.9" +version = "3.17.0" description = "PEP-484 stubs for django-rest-framework" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "djangorestframework_stubs-3.16.9-py3-none-any.whl", hash = "sha256:27b3e245d5f9c22ff6988d9e54388249f98f88608cc2b365b71e9f39dd096958"}, - {file = "djangorestframework_stubs-3.16.9.tar.gz", hash = "sha256:b1abb97490c90c85eabcd09b8ecbadae1b9360f21ad3021abf830227c0129697"}, + {file = "djangorestframework_stubs-3.17.0-py3-none-any.whl", hash = "sha256:babe2703f0401507780848439f49f76222a178b4fc73a6dcb30d0952a0a6dbc6"}, + {file = "djangorestframework_stubs-3.17.0.tar.gz", hash = "sha256:74c0307cad304c03c15aee5955ec2fdeab0ac854b5bea569dc124892792e2b96"}, ] [package.dependencies] -django-stubs = ">=5.2.9" +django-stubs = ">=6.0.4" types-pyyaml = "*" typing-extensions = ">=4.0" [package.extras] -compatible-mypy = ["django-stubs[compatible-mypy]", "mypy (>=1.13,<1.21)"] +compatible-mypy = ["django-stubs[compatible-mypy]", "mypy (>=1.13,<2.2)"] coreapi = ["coreapi (>=2.0.0)"] markdown = ["types-markdown (>=0.1.5)"] requests = ["types-requests"] @@ -1558,21 +1529,24 @@ sidecar = ["drf-spectacular-sidecar"] [[package]] name = "dropbox" -version = "12.0.2" +version = "12.2.1" description = "Official Dropbox API Client" optional = false -python-versions = "*" +python-versions = ">=3.11" groups = ["main"] files = [ - {file = "dropbox-12.0.2-py2-none-any.whl", hash = "sha256:4b8207a9f4afd33726ec886c0d223f4bbc42fe649b87718690a24704f5e24c0c"}, - {file = "dropbox-12.0.2-py3-none-any.whl", hash = "sha256:c5b7e9c2668adb6b12dcecd84342565dc50f7d35ab6a748d155cb79040979d1c"}, - {file = "dropbox-12.0.2.tar.gz", hash = "sha256:50057fd5ad5fcf047f542dfc6747a896e7ef982f1b5f8500daf51f3abd609962"}, + {file = "dropbox-12.2.1-py3-none-any.whl", hash = "sha256:a0f9cdc3505b104f7a14b35f81a8a0be6f44eb738475ef324243684c25efe1fb"}, + {file = "dropbox-12.2.1.tar.gz", hash = "sha256:61fcb821f7e8585aa4b9e2abc94801aaf8d65ed5ca89313450e56d51c46add7e"}, ] [package.dependencies] requests = ">=2.16.2" -six = ">=1.12.0" -stone = ">=2,<3.3.3" +stone = ">=3.5.3,<4" + +[package.extras] +dev = ["build", "flake8", "twine", "wheel"] +docs = ["sphinx", "sphinx_rtd_theme"] +test = ["coverage", "mock", "pytest", "pytest-mock", "stone (>=3.5.3,<4)"] [[package]] name = "et-xmlfile" @@ -1603,14 +1577,14 @@ tests = ["pytest"] [[package]] name = "faker" -version = "40.15.0" +version = "40.36.0" description = "Faker is a Python package that generates fake data for you." optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "faker-40.15.0-py3-none-any.whl", hash = "sha256:71ab3c3370da9d2205ab74ffb0fd51273063ad562b3a3bb69d0026a20923e318"}, - {file = "faker-40.15.0.tar.gz", hash = "sha256:20f3a6ec8c266b74d4c554e34118b21c3c2056c0b4a519d15c8decb3a4e6e795"}, + {file = "faker-40.36.0-py3-none-any.whl", hash = "sha256:82b9497d9cfe017048075bcf969298a74b1b6e39f5e4dad1211085d1133f7b62"}, + {file = "faker-40.36.0.tar.gz", hash = "sha256:754048c76c03afa7de83eee8f4bcee3cf668cbb7d995f54a4e9678db7f110308"}, ] [package.dependencies] @@ -1710,14 +1684,14 @@ files = [ [[package]] name = "filelock" -version = "3.29.0" +version = "3.32.0" description = "A platform independent file lock." optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258"}, - {file = "filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90"}, + {file = "filelock-3.32.0-py3-none-any.whl", hash = "sha256:d396bea984af47333ef05e50eae7eff88c84256de6112aea0ec48a233c064fe3"}, + {file = "filelock-3.32.0.tar.gz", hash = "sha256:7be2ad23a14607ccc71808e68fe30848aeace7058ace17852f68e2a68e310402"}, ] [[package]] @@ -1756,62 +1730,62 @@ dev = ["Flit (>=3.4)", "pyTest (>=7)", "pyTest-cov (>=7) ; python_version >= \"3 [[package]] name = "fonttools" -version = "4.62.1" +version = "4.63.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "fonttools-4.62.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ad5cca75776cd453b1b035b530e943334957ae152a36a88a320e779d61fc980c"}, - {file = "fonttools-4.62.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b3ae47e8636156a9accff64c02c0924cbebad62854c4a6dbdc110cd5b4b341a"}, - {file = "fonttools-4.62.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9b9e288b4da2f64fd6180644221749de651703e8d0c16bd4b719533a3a7d6e3"}, - {file = "fonttools-4.62.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7bca7a1c1faf235ffe25d4f2e555246b4750220b38de8261d94ebc5ce8a23c23"}, - {file = "fonttools-4.62.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b4e0fcf265ad26e487c56cb12a42dffe7162de708762db951e1b3f755319507d"}, - {file = "fonttools-4.62.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2d850f66830a27b0d498ee05adb13a3781637b1826982cd7e2b3789ef0cc71ae"}, - {file = "fonttools-4.62.1-cp310-cp310-win32.whl", hash = "sha256:486f32c8047ccd05652aba17e4a8819a3a9d78570eb8a0e3b4503142947880ed"}, - {file = "fonttools-4.62.1-cp310-cp310-win_amd64.whl", hash = "sha256:5a648bde915fba9da05ae98856987ca91ba832949a9e2888b48c47ef8b96c5a9"}, - {file = "fonttools-4.62.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:40975849bac44fb0b9253d77420c6d8b523ac4dcdcefeff6e4d706838a5b80f7"}, - {file = "fonttools-4.62.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9dde91633f77fa576879a0c76b1d89de373cae751a98ddf0109d54e173b40f14"}, - {file = "fonttools-4.62.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6acb4109f8bee00fec985c8c7afb02299e35e9c94b57287f3ea542f28bd0b0a7"}, - {file = "fonttools-4.62.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1c5c25671ce8805e0d080e2ffdeca7f1e86778c5cbfbeae86d7f866d8830517b"}, - {file = "fonttools-4.62.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a5d8825e1140f04e6c99bb7d37a9e31c172f3bc208afbe02175339e699c710e1"}, - {file = "fonttools-4.62.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:268abb1cb221e66c014acc234e872b7870d8b5d4657a83a8f4205094c32d2416"}, - {file = "fonttools-4.62.1-cp311-cp311-win32.whl", hash = "sha256:942b03094d7edbb99bdf1ae7e9090898cad7bf9030b3d21f33d7072dbcb51a53"}, - {file = "fonttools-4.62.1-cp311-cp311-win_amd64.whl", hash = "sha256:e8514f4924375f77084e81467e63238b095abda5107620f49421c368a6017ed2"}, - {file = "fonttools-4.62.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:90365821debbd7db678809c7491ca4acd1e0779b9624cdc6ddaf1f31992bf974"}, - {file = "fonttools-4.62.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12859ff0b47dd20f110804c3e0d0970f7b832f561630cd879969011541a464a9"}, - {file = "fonttools-4.62.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c125ffa00c3d9003cdaaf7f2c79e6e535628093e14b5de1dccb08859b680936"}, - {file = "fonttools-4.62.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:149f7d84afca659d1a97e39a4778794a2f83bf344c5ee5134e09995086cc2392"}, - {file = "fonttools-4.62.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0aa72c43a601cfa9273bb1ae0518f1acadc01ee181a6fc60cd758d7fdadffc04"}, - {file = "fonttools-4.62.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:19177c8d96c7c36359266e571c5173bcee9157b59cfc8cb0153c5673dc5a3a7d"}, - {file = "fonttools-4.62.1-cp312-cp312-win32.whl", hash = "sha256:a24decd24d60744ee8b4679d38e88b8303d86772053afc29b19d23bb8207803c"}, - {file = "fonttools-4.62.1-cp312-cp312-win_amd64.whl", hash = "sha256:9e7863e10b3de72376280b515d35b14f5eeed639d1aa7824f4cf06779ec65e42"}, - {file = "fonttools-4.62.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c22b1014017111c401469e3acc5433e6acf6ebcc6aa9efb538a533c800971c79"}, - {file = "fonttools-4.62.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68959f5fc58ed4599b44aad161c2837477d7f35f5f79402d97439974faebfebe"}, - {file = "fonttools-4.62.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef46db46c9447103b8f3ff91e8ba009d5fe181b1920a83757a5762551e32bb68"}, - {file = "fonttools-4.62.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6706d1cb1d5e6251a97ad3c1b9347505c5615c112e66047abbef0f8545fa30d1"}, - {file = "fonttools-4.62.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2e7abd2b1e11736f58c1de27819e1955a53267c21732e78243fa2fa2e5c1e069"}, - {file = "fonttools-4.62.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:403d28ce06ebfc547fbcb0cb8b7f7cc2f7a2d3e1a67ba9a34b14632df9e080f9"}, - {file = "fonttools-4.62.1-cp313-cp313-win32.whl", hash = "sha256:93c316e0f5301b2adbe6a5f658634307c096fd5aae60a5b3412e4f3e1728ab24"}, - {file = "fonttools-4.62.1-cp313-cp313-win_amd64.whl", hash = "sha256:7aa21ff53e28a9c2157acbc44e5b401149d3c9178107130e82d74ceb500e5056"}, - {file = "fonttools-4.62.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fa1d16210b6b10a826d71bed68dd9ec24a9e218d5a5e2797f37c573e7ec215ca"}, - {file = "fonttools-4.62.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:aa69d10ed420d8121118e628ad47d86e4caa79ba37f968597b958f6cceab7eca"}, - {file = "fonttools-4.62.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd13b7999d59c5eb1c2b442eb2d0c427cb517a0b7a1f5798fc5c9e003f5ff782"}, - {file = "fonttools-4.62.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8d337fdd49a79b0d51c4da87bc38169d21c3abbf0c1aa9367eff5c6656fb6dae"}, - {file = "fonttools-4.62.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d241cdc4a67b5431c6d7f115fdf63335222414995e3a1df1a41e1182acd4bcc7"}, - {file = "fonttools-4.62.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c05557a78f8fa514da0f869556eeda40887a8abc77c76ee3f74cf241778afd5a"}, - {file = "fonttools-4.62.1-cp314-cp314-win32.whl", hash = "sha256:49a445d2f544ce4a69338694cad575ba97b9a75fff02720da0882d1a73f12800"}, - {file = "fonttools-4.62.1-cp314-cp314-win_amd64.whl", hash = "sha256:1eecc128c86c552fb963fe846ca4e011b1be053728f798185a1687502f6d398e"}, - {file = "fonttools-4.62.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:1596aeaddf7f78e21e68293c011316a25267b3effdaccaf4d59bc9159d681b82"}, - {file = "fonttools-4.62.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8f8fca95d3bb3208f59626a4b0ea6e526ee51f5a8ad5d91821c165903e8d9260"}, - {file = "fonttools-4.62.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee91628c08e76f77b533d65feb3fbe6d9dad699f95be51cf0d022db94089cdc4"}, - {file = "fonttools-4.62.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5f37df1cac61d906e7b836abe356bc2f34c99d4477467755c216b72aa3dc748b"}, - {file = "fonttools-4.62.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:92bb00a947e666169c99b43753c4305fc95a890a60ef3aeb2a6963e07902cc87"}, - {file = "fonttools-4.62.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:bdfe592802ef939a0e33106ea4a318eeb17822c7ee168c290273cbd5fabd746c"}, - {file = "fonttools-4.62.1-cp314-cp314t-win32.whl", hash = "sha256:b820fcb92d4655513d8402d5b219f94481c4443d825b4372c75a2072aa4b357a"}, - {file = "fonttools-4.62.1-cp314-cp314t-win_amd64.whl", hash = "sha256:59b372b4f0e113d3746b88985f1c796e7bf830dd54b28374cd85c2b8acd7583e"}, - {file = "fonttools-4.62.1-py3-none-any.whl", hash = "sha256:7487782e2113861f4ddcc07c3436450659e3caa5e470b27dc2177cade2d8e7fd"}, - {file = "fonttools-4.62.1.tar.gz", hash = "sha256:e54c75fd6041f1122476776880f7c3c3295ffa31962dc6ebe2543c00dca58b5d"}, + {file = "fonttools-4.63.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e3297a6a4059b4acc3a1e9a8b04741f240a80044eef08ebd32e8b5bcdddce75b"}, + {file = "fonttools-4.63.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b1cd75a03ad8cb5bc40c90bfde68c0c47de423aa19e5c0f362b43520645eea94"}, + {file = "fonttools-4.63.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0425b277a59cff3d80ca42162a8de360f318438a2ac83570842a678d826d579"}, + {file = "fonttools-4.63.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d7e5c9973aa04c95650c96e5f5ad865fbf42d62079163ecfab1e01cbc2504c22"}, + {file = "fonttools-4.63.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cb014d58140a38135f16064c74c652ed57aa0b75cbf8bb59cac821f7edb5334e"}, + {file = "fonttools-4.63.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:032038247a96c1690f9f31e377c389383c902531b085aa4e4dabd6f57f870e69"}, + {file = "fonttools-4.63.0-cp310-cp310-win32.whl", hash = "sha256:a8b33a82979e0a6a34ff435cc81317be1f95ec1ebb7a3a2d1c8a6a54f02ae44e"}, + {file = "fonttools-4.63.0-cp310-cp310-win_amd64.whl", hash = "sha256:0c18358a155d75034911c5ee397a5b44cd19dd325dbb8b35fb60bf421d6a72ac"}, + {file = "fonttools-4.63.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b8ae05d9eacf6081414d759c0a352769ac28ce31280d6bb8e77b03f9e3c449f"}, + {file = "fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79cdc9f567aec74a72918fd060283911406750cbc9fd28c1316023deb6ce31a9"}, + {file = "fonttools-4.63.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c14b4fd138c4bafcca294765c547914e1aa431ae1ca94ab99d8db08c958bd3b"}, + {file = "fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76ac49f929aecaf82d83250b8347e099d7aecba0f4726c1d9b6df3b8bb5fe18"}, + {file = "fonttools-4.63.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dcf076a4474fe0d7367e5bbf5b052c7284fa1feca729c04176ce513521afd8a0"}, + {file = "fonttools-4.63.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7dd683fef0663e9f0f45cf541d788d24caa3ec9db50796b588e1757d8b3bc007"}, + {file = "fonttools-4.63.0-cp311-cp311-win32.whl", hash = "sha256:afefc1ed0a59785a7fb06ea7e1678e849c193e1e387db783579bc7b3056fcfcb"}, + {file = "fonttools-4.63.0-cp311-cp311-win_amd64.whl", hash = "sha256:063e08bd17bd5a90127a14123de0d6a952dbc847695fd98b63c043d58057f90c"}, + {file = "fonttools-4.63.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02"}, + {file = "fonttools-4.63.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0"}, + {file = "fonttools-4.63.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af"}, + {file = "fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8"}, + {file = "fonttools-4.63.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b"}, + {file = "fonttools-4.63.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78"}, + {file = "fonttools-4.63.0-cp312-cp312-win32.whl", hash = "sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263"}, + {file = "fonttools-4.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272"}, + {file = "fonttools-4.63.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd"}, + {file = "fonttools-4.63.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59"}, + {file = "fonttools-4.63.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d"}, + {file = "fonttools-4.63.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68"}, + {file = "fonttools-4.63.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be"}, + {file = "fonttools-4.63.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27"}, + {file = "fonttools-4.63.0-cp313-cp313-win32.whl", hash = "sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380"}, + {file = "fonttools-4.63.0-cp313-cp313-win_amd64.whl", hash = "sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b"}, + {file = "fonttools-4.63.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fd1e3094f42d806d3d7c79162fc59e5910fcbe3a7360c385b8da969bc4493745"}, + {file = "fonttools-4.63.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6e528da43bc3791085f8cb6141b1d13e459226790240340fcbb4625649238b03"}, + {file = "fonttools-4.63.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b2248c5decb223562f7902ff6325077a073f608ee8e33e88ad88db734eb9f49"}, + {file = "fonttools-4.63.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:308f957cdeaf8abe4e5f2f124902ef405448af92c90f80e302a3b771c2e6116b"}, + {file = "fonttools-4.63.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bf00f21eb5fb721dbaf73d1e9da6d02a1af7768f2ebcf9798be98beab8ba90f6"}, + {file = "fonttools-4.63.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c1aaa4b9c75798400ac043ce04d74e7830376c85095a5a6ed7cba2f17a266bf4"}, + {file = "fonttools-4.63.0-cp314-cp314-win32.whl", hash = "sha256:22693918177bd9ceabec4736d338045f357769416fc6b0b2508eefef75b08616"}, + {file = "fonttools-4.63.0-cp314-cp314-win_amd64.whl", hash = "sha256:7d782fac32985914c351556f68ac0855391572bcd87de50e05970d3cd4c96fc5"}, + {file = "fonttools-4.63.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:6db5140a60a5d731d21ec076745b40a310607731b0a565b50776393188649001"}, + {file = "fonttools-4.63.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d76edbff9014094dbf03bd2d074709dfa6ec7aba13d838c937a2b33d2d6a86e"}, + {file = "fonttools-4.63.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0eac00b9118c3c2f87d272e45341871c5b3066baa3c86897fa634a7c3fb59096"}, + {file = "fonttools-4.63.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51394295f1a51de8b5f30bdb1e1b9a4231536c7064ef5c6e211eec19fa36036f"}, + {file = "fonttools-4.63.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9e12f105d2b6342c559c298afb674006bb2893afc7102dcf8a1b55b0486b4e40"}, + {file = "fonttools-4.63.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:796f27556dbe094c4824f75ca85267e4df776c79036c8441469a4df37038c196"}, + {file = "fonttools-4.63.0-cp314-cp314t-win32.whl", hash = "sha256:948428a275741f0b64b113c955425a953314f4b9ab9997f73a72c83e68e569c8"}, + {file = "fonttools-4.63.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6d4741eb179121cab9eea4cb2393d24492373a260d7945006358c08cfbf45419"}, + {file = "fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d"}, + {file = "fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0"}, ] [package.extras] @@ -2024,94 +1998,42 @@ test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask[dataframe,test]", "moto test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "backports-zstd ; python_version < \"3.14\"", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas (<3.0.0)", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr (<3.2.0)", "zstandard ; python_version < \"3.14\""] tqdm = ["tqdm"] -[[package]] -name = "google-ai-generativelanguage" -version = "0.6.15" -description = "Google Ai Generativelanguage API client library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "google_ai_generativelanguage-0.6.15-py3-none-any.whl", hash = "sha256:5a03ef86377aa184ffef3662ca28f19eeee158733e45d7947982eb953c6ebb6c"}, - {file = "google_ai_generativelanguage-0.6.15.tar.gz", hash = "sha256:8f6d9dc4c12b065fe2d0289026171acea5183ebf2d0b11cefe12f3821e159ec3"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0.dev0", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" -proto-plus = [ - {version = ">=1.25.0,<2.0.0.dev0", markers = "python_version >= \"3.13\""}, - {version = ">=1.22.3,<2.0.0.dev0"}, -] -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" - [[package]] name = "google-api-core" -version = "2.25.2" +version = "2.33.0" description = "Google API client core library" optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version >= \"3.14\"" -files = [ - {file = "google_api_core-2.25.2-py3-none-any.whl", hash = "sha256:e9a8f62d363dc8424a8497f4c2a47d6bcda6c16514c935629c257ab5d10210e7"}, - {file = "google_api_core-2.25.2.tar.gz", hash = "sha256:1c63aa6af0d0d5e37966f157a77f9396d820fba59f9e43e9415bc3dc5baff300"}, -] - -[package.dependencies] -google-auth = ">=2.14.1,<3.0.0" -googleapis-common-protos = ">=1.56.2,<2.0.0" -grpcio = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} -grpcio-status = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} -proto-plus = {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""} -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<7.0.0" -requests = ">=2.18.0,<3.0.0" - -[package.extras] -async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.0)"] -grpc = ["grpcio (>=1.33.2,<2.0.0)", "grpcio (>=1.49.1,<2.0.0) ; python_version >= \"3.11\"", "grpcio-status (>=1.33.2,<2.0.0)", "grpcio-status (>=1.49.1,<2.0.0) ; python_version >= \"3.11\""] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.0)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.0)"] - -[[package]] -name = "google-api-core" -version = "2.30.3" -description = "Google API client core library" -optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] -markers = "python_version < \"3.14\"" files = [ - {file = "google_api_core-2.30.3-py3-none-any.whl", hash = "sha256:a85761ba72c444dad5d611c2220633480b2b6be2521eca69cca2dbb3ffd6bfe8"}, - {file = "google_api_core-2.30.3.tar.gz", hash = "sha256:e601a37f148585319b26db36e219df68c5d07b6382cff2d580e83404e44d641b"}, + {file = "google_api_core-2.33.0-py3-none-any.whl", hash = "sha256:a2e22a0c1d0f03eafff1858b38cf46f832d5902b0c052235bf0ab8402929fbdc"}, + {file = "google_api_core-2.33.0.tar.gz", hash = "sha256:3a36bcc3e319783f4c97da41f6f45ea6ffcaa55848e341de16e09cb70243c2bb"}, ] [package.dependencies] google-auth = ">=2.14.1,<3.0.0" googleapis-common-protos = ">=1.63.2,<2.0.0" -grpcio = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} -grpcio-status = {version = ">=1.49.1,<2.0.0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} proto-plus = [ {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, - {version = ">=1.22.3,<2.0.0", markers = "python_version < \"3.13\""}, + {version = ">=1.24.0,<2.0.0", markers = "python_version < \"3.13\""}, ] -protobuf = ">=4.25.8,<8.0.0" -requests = ">=2.20.0,<3.0.0" +protobuf = ">=5.29.6,<8.0.0" +requests = ">=2.33.0,<3.0.0" [package.extras] -async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.0)"] -grpc = ["grpcio (>=1.33.2,<2.0.0)", "grpcio (>=1.49.1,<2.0.0) ; python_version >= \"3.11\"", "grpcio (>=1.75.1,<2.0.0) ; python_version >= \"3.14\"", "grpcio-status (>=1.33.2,<2.0.0)", "grpcio-status (>=1.49.1,<2.0.0) ; python_version >= \"3.11\"", "grpcio-status (>=1.75.1,<2.0.0) ; python_version >= \"3.14\""] +async-rest = ["aiohttp (>=3.13.4)", "google-auth[aiohttp] (>=2.14.1,<3.0.0)"] +grpc = ["grpcio (>=1.41.0,<2.0.0)", "grpcio (>=1.49.1,<2.0.0) ; python_version >= \"3.11\"", "grpcio (>=1.75.1,<2.0.0) ; python_version >= \"3.14\"", "grpcio-status (>=1.41.0,<2.0.0)", "grpcio-status (>=1.49.1,<2.0.0) ; python_version >= \"3.11\"", "grpcio-status (>=1.75.1,<2.0.0) ; python_version >= \"3.14\""] [[package]] name = "google-api-python-client" -version = "2.195.0" +version = "2.198.0" description = "Google API Client Library for Python" optional = false python-versions = ">=3.7" groups = ["main", "dev"] files = [ - {file = "google_api_python_client-2.195.0-py3-none-any.whl", hash = "sha256:753e62057f23049a89534bea0162b60fe391b85fb86d80bcdf884d05ec91c5bf"}, - {file = "google_api_python_client-2.195.0.tar.gz", hash = "sha256:c72cf2661c3addf01c880ce60541e83e1df354644b874f7f9d8d5ed2070446ae"}, + {file = "google_api_python_client-2.198.0-py3-none-any.whl", hash = "sha256:fabac935474e817da5e662ff61bf7139439d6f92b32d332a7318a2d45931e03e"}, + {file = "google_api_python_client-2.198.0.tar.gz", hash = "sha256:dfe3e16fb241af6e9c460a33f65085b3450e05cea09364f6b5d8997fb7e43e2a"}, ] [package.dependencies] @@ -2140,43 +2062,47 @@ typing-extensions = ">=3.10.0" [[package]] name = "google-auth" -version = "2.53.0" +version = "2.56.2" description = "Google Authentication Library" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "google_auth-2.53.0-py3-none-any.whl", hash = "sha256:6e7449917c599b35126a99ec268ec6880301f2fea41dce198fe8fd83ff642b68"}, - {file = "google_auth-2.53.0.tar.gz", hash = "sha256:e7e6aa16f6bee7b2b264830fd04f08087a1d5a836df516251a5d15327b246c9c"}, + {file = "google_auth-2.56.2-py3-none-any.whl", hash = "sha256:c8270ea95b2697b74e3d8438ae9c5b898e38b623b915c7b5c5635921e7de68a6"}, + {file = "google_auth-2.56.2.tar.gz", hash = "sha256:e28f103ca8091fb7012b99c44243d7366c29863713b8e34a220c3322b7a07051"}, ] [package.dependencies] -cryptography = ">=38.0.3" +cryptography = [ + {version = ">=38.0.3", markers = "python_version < \"3.14\""}, + {version = ">=41.0.5", markers = "python_version >= \"3.14\""}, +] pyasn1-modules = ">=0.2.1" -requests = {version = ">=2.20.0,<3.0.0", optional = true, markers = "extra == \"requests\""} +requests = {version = ">=2.30.0,<3.0.0", optional = true, markers = "extra == \"requests\""} [package.extras] -aiohttp = ["aiohttp (>=3.8.0,<4.0.0)", "requests (>=2.20.0,<3.0.0)"] -cryptography = ["cryptography (>=38.0.3)"] -enterprise-cert = ["pyopenssl"] +aiohttp = ["aiohttp (>=3.8.0,<4.0.0) ; python_version < \"3.14\"", "aiohttp (>=3.9.0,<4.0.0) ; python_version >= \"3.14\"", "requests (>=2.30.0,<3.0.0)"] +cryptography = ["cryptography (>=38.0.3) ; python_version < \"3.14\"", "cryptography (>=41.0.5) ; python_version >= \"3.14\""] +enterprise-cert = ["cryptography (>=38.0.3) ; python_version < \"3.14\"", "cryptography (>=41.0.5) ; python_version >= \"3.14\""] +grpc = ["grpcio (>=1.59.0,<2.0.0) ; python_version < \"3.14\"", "grpcio (>=1.75.1,<2.0.0) ; python_version >= \"3.14\""] pyjwt = ["pyjwt (>=2.0)"] -pyopenssl = ["pyopenssl (>=20.0.0)"] +pyopenssl = ["cryptography (>=38.0.3) ; python_version < \"3.14\"", "cryptography (>=41.0.5) ; python_version >= \"3.14\""] reauth = ["pyu2f (>=0.1.5)"] -requests = ["requests (>=2.20.0,<3.0.0)"] -rsa = ["rsa (>=3.1.4,<5)"] -testing = ["aiohttp (<3.10.0)", "aiohttp (>=3.8.0,<4.0.0)", "aioresponses", "flask", "freezegun", "grpcio", "packaging", "pyjwt (>=2.0)", "pyopenssl (<24.3.0)", "pyopenssl (>=20.0.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.20.0,<3.0.0)", "responses", "urllib3"] -urllib3 = ["packaging", "urllib3"] +requests = ["requests (>=2.30.0,<3.0.0)"] +rsa = ["rsa (>=4.0.0,<5)"] +testing = ["aiohttp (>=3.8.0,<4.0.0) ; python_version < \"3.14\"", "aiohttp (>=3.9.0,<4.0.0) ; python_version >= \"3.14\"", "aioresponses", "flask", "freezegun", "grpcio (>=1.59.0,<2.0.0) ; python_version < \"3.14\"", "grpcio (>=1.75.1,<2.0.0) ; python_version >= \"3.14\"", "packaging (>=20.0)", "pyjwt (>=2.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-localserver", "pyu2f (>=0.1.5)", "requests (>=2.30.0,<3.0.0)", "responses", "urllib3 (>=1.26.15,<3.0.0)"] +urllib3 = ["packaging (>=20.0)", "urllib3 (>=1.26.15,<3.0.0)"] [[package]] name = "google-auth-httplib2" -version = "0.3.1" +version = "0.4.0" description = "Google Authentication Library: httplib2 transport" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "google_auth_httplib2-0.3.1-py3-none-any.whl", hash = "sha256:682356a90ef4ba3d06548c37e9112eea6fc00395a11b0303a644c1a86abc275c"}, - {file = "google_auth_httplib2-0.3.1.tar.gz", hash = "sha256:0af542e815784cb64159b4469aa5d71dd41069ba93effa006e1916b1dcd88e55"}, + {file = "google_auth_httplib2-0.4.0-py3-none-any.whl", hash = "sha256:8e55cfafa3358cba85f6cad4a886138e88e158d71e7e5c9ee5936a5c1507fb91"}, + {file = "google_auth_httplib2-0.4.0.tar.gz", hash = "sha256:d5b030a204b7a4b4d553ba9ca701b62481ee2b74419325580be70f7d85ffed35"}, ] [package.dependencies] @@ -2202,20 +2128,20 @@ types-requests = ">=2.25.9,<3.0.0" [[package]] name = "google-genai" -version = "2.10.0" +version = "2.14.0" description = "GenAI Python SDK" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "google_genai-2.10.0-py3-none-any.whl", hash = "sha256:d5350311567ae660c24cbc1752aee4b3d660f89c0106d2dcd2a69978c35afe1e"}, - {file = "google_genai-2.10.0.tar.gz", hash = "sha256:77912cd558cd7dfd5b75c25fd1c609e78d7954dde583331104022a46ea90f9ee"}, + {file = "google_genai-2.14.0-py3-none-any.whl", hash = "sha256:ae7172cdd35695189b516b33a878e4132e5daa2dbc03a5b44cddfa8a82fad664"}, + {file = "google_genai-2.14.0.tar.gz", hash = "sha256:a9d1f4f362d76280f1be1340fcb3c86e63dbca128f6a4ae09d86ab47ff7148e8"}, ] [package.dependencies] anyio = ">=4.8.0,<5.0.0" distro = ">=1.7.0,<2" -google-auth = {version = ">=2.48.1,<3.0.0", extras = ["requests"]} +google-auth = {version = ">=2.56.0,<3.0.0", extras = ["requests"]} httpx = ">=0.28.1,<1.0.0" pydantic = ">=2.12.5,<3.0.0" requests = ">=2.28.1,<3.0.0" @@ -2229,40 +2155,16 @@ aiohttp = ["aiohttp (>=3.10.11,<4.0.0)"] local-tokenizer = ["pillow", "protobuf", "sentencepiece (>=0.2.0)", "torch", "torchvision", "transformers"] pyopenssl = ["pyopenssl"] -[[package]] -name = "google-generativeai" -version = "0.8.6" -description = "Google Generative AI High level API client library and tools." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "google_generativeai-0.8.6-py3-none-any.whl", hash = "sha256:37a0eaaa95e5bbf888828e20a4a1b2c196cc9527d194706e58a68ff388aeb0fa"}, -] - -[package.dependencies] -google-ai-generativelanguage = "0.6.15" -google-api-core = "*" -google-api-python-client = "*" -google-auth = ">=2.15.0" -protobuf = "*" -pydantic = "*" -tqdm = "*" -typing-extensions = "*" - -[package.extras] -dev = ["Pillow", "absl-py", "black", "ipython", "nose2", "pandas", "pytype", "pyyaml"] - [[package]] name = "googleapis-common-protos" -version = "1.74.0" +version = "1.75.0" description = "Common protobufs used in Google APIs" optional = false python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "googleapis_common_protos-1.74.0-py3-none-any.whl", hash = "sha256:702216f78610bb510e3f12ac3cafd281b7ac45cc5d86e90ad87e4d301a3426b5"}, - {file = "googleapis_common_protos-1.74.0.tar.gz", hash = "sha256:57971e4eeeba6aad1163c1f0fc88543f965bb49129b8bb55b2b7b26ecab084f1"}, + {file = "googleapis_common_protos-1.75.0-py3-none-any.whl", hash = "sha256:961ed60399c457ceb0ee8f285a84c870aabc9c6a832b9d37bb281b5bebde43ed"}, + {file = "googleapis_common_protos-1.75.0.tar.gz", hash = "sha256:53a062ff3c32552fbd62c11fe23768b78e4ddf0494d5e5fd97d3f4689c75fbbd"}, ] [package.dependencies] @@ -2288,97 +2190,70 @@ grpcio = "*" [[package]] name = "grpcio" -version = "1.80.0" +version = "1.83.0" description = "HTTP/2-based RPC framework" optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "grpcio-1.80.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:886457a7768e408cdce226ad1ca67d2958917d306523a0e21e1a2fdaa75c9c9c"}, - {file = "grpcio-1.80.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:7b641fc3f1dc647bfd80bd713addc68f6d145956f64677e56d9ebafc0bd72388"}, - {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:33eb763f18f006dc7fee1e69831d38d23f5eccd15b2e0f92a13ee1d9242e5e02"}, - {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:52d143637e3872633fc7dd7c3c6a1c84e396b359f3a72e215f8bf69fd82084fc"}, - {file = "grpcio-1.80.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c51bf8ac4575af2e0678bccfb07e47321fc7acb5049b4482832c5c195e04e13a"}, - {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:50a9871536d71c4fba24ee856abc03a87764570f0c457dd8db0b4018f379fed9"}, - {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a72d84ad0514db063e21887fbacd1fd7acb4d494a564cae22227cd45c7fbf199"}, - {file = "grpcio-1.80.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f7691a6788ad9196872f95716df5bc643ebba13c97140b7a5ee5c8e75d1dea81"}, - {file = "grpcio-1.80.0-cp310-cp310-win32.whl", hash = "sha256:46c2390b59d67f84e882694d489f5b45707c657832d7934859ceb8c33f467069"}, - {file = "grpcio-1.80.0-cp310-cp310-win_amd64.whl", hash = "sha256:dc053420fc75749c961e2a4c906398d7c15725d36ccc04ae6d16093167223b58"}, - {file = "grpcio-1.80.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:dfab85db094068ff42e2a3563f60ab3dddcc9d6488a35abf0132daec13209c8a"}, - {file = "grpcio-1.80.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5c07e82e822e1161354e32da2662f741a4944ea955f9f580ec8fb409dd6f6060"}, - {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba0915d51fd4ced2db5ff719f84e270afe0e2d4c45a7bdb1e8d036e4502928c2"}, - {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:3cb8130ba457d2aa09fa6b7c3ed6b6e4e6a2685fce63cb803d479576c4d80e21"}, - {file = "grpcio-1.80.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:09e5e478b3d14afd23f12e49e8b44c8684ac3c5f08561c43a5b9691c54d136ab"}, - {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:00168469238b022500e486c1c33916acf2f2a9b2c022202cf8a1885d2e3073c1"}, - {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8502122a3cc1714038e39a0b071acb1207ca7844208d5ea0d091317555ee7106"}, - {file = "grpcio-1.80.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ce1794f4ea6cc3ca29463f42d665c32ba1b964b48958a66497917fe9069f26e6"}, - {file = "grpcio-1.80.0-cp311-cp311-win32.whl", hash = "sha256:51b4a7189b0bef2aa30adce3c78f09c83526cf3dddb24c6a96555e3b97340440"}, - {file = "grpcio-1.80.0-cp311-cp311-win_amd64.whl", hash = "sha256:02e64bb0bb2da14d947a49e6f120a75e947250aebe65f9629b62bb1f5c14e6e9"}, - {file = "grpcio-1.80.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:c624cc9f1008361014378c9d776de7182b11fe8b2e5a81bc69f23a295f2a1ad0"}, - {file = "grpcio-1.80.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:f49eddcac43c3bf350c0385366a58f36bed8cc2c0ec35ef7b74b49e56552c0c2"}, - {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d334591df610ab94714048e0d5b4f3dd5ad1bee74dfec11eee344220077a79de"}, - {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0cb517eb1d0d0aaf1d87af7cc5b801d686557c1d88b2619f5e31fab3c2315921"}, - {file = "grpcio-1.80.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e78c4ac0d97dc2e569b2f4bcbbb447491167cb358d1a389fc4af71ab6f70411"}, - {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2ed770b4c06984f3b47eb0517b1c69ad0b84ef3f40128f51448433be904634cd"}, - {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:256507e2f524092f1473071a05e65a5b10d84b82e3ff24c5b571513cfaa61e2f"}, - {file = "grpcio-1.80.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a6284a5d907c37db53350645567c522be314bac859a64a7a5ca63b77bb7958f"}, - {file = "grpcio-1.80.0-cp312-cp312-win32.whl", hash = "sha256:c71309cfce2f22be26aa4a847357c502db6c621f1a49825ae98aa0907595b193"}, - {file = "grpcio-1.80.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe648599c0e37594c4809d81a9e77bd138cc82eb8baa71b6a86af65426723ff"}, - {file = "grpcio-1.80.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:e9e408fc016dffd20661f0126c53d8a31c2821b5c13c5d67a0f5ed5de93319ad"}, - {file = "grpcio-1.80.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:92d787312e613754d4d8b9ca6d3297e69994a7912a32fa38c4c4e01c272974b0"}, - {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8ac393b58aa16991a2f1144ec578084d544038c12242da3a215966b512904d0f"}, - {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:68e5851ac4b9afe07e7f84483803ad167852570d65326b34d54ca560bfa53fb6"}, - {file = "grpcio-1.80.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:873ff5d17d68992ef6605330127425d2fc4e77e612fa3c3e0ed4e668685e3140"}, - {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2bea16af2750fd0a899bf1abd9022244418b55d1f37da2202249ba4ba673838d"}, - {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba0db34f7e1d803a878284cd70e4c63cb6ae2510ba51937bf8f45ba997cefcf7"}, - {file = "grpcio-1.80.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8eb613f02d34721f1acf3626dfdb3545bd3c8505b0e52bf8b5710a28d02e8aa7"}, - {file = "grpcio-1.80.0-cp313-cp313-win32.whl", hash = "sha256:93b6f823810720912fd131f561f91f5fed0fda372b6b7028a2681b8194d5d294"}, - {file = "grpcio-1.80.0-cp313-cp313-win_amd64.whl", hash = "sha256:e172cf795a3ba5246d3529e4d34c53db70e888fa582a8ffebd2e6e48bc0cba50"}, - {file = "grpcio-1.80.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:3d4147a97c8344d065d01bbf8b6acec2cf86fb0400d40696c8bdad34a64ffc0e"}, - {file = "grpcio-1.80.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d8e11f167935b3eb089ac9038e1a063e6d7dbe995c0bb4a661e614583352e76f"}, - {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f14b618fc30de822681ee986cfdcc2d9327229dc4c98aed16896761cacd468b9"}, - {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4ed39fbdcf9b87370f6e8df4e39ca7b38b3e5e9d1b0013c7b6be9639d6578d14"}, - {file = "grpcio-1.80.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2dcc70e9f0ba987526e8e8603a610fb4f460e42899e74e7a518bf3c68fe1bf05"}, - {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:448c884b668b868562b1bda833c5fce6272d26e1926ec46747cda05741d302c1"}, - {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a1dc80fe55685b4a543555e6eef975303b36c8db1023b1599b094b92aa77965f"}, - {file = "grpcio-1.80.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:31b9ac4ad1aa28ffee5503821fafd09e4da0a261ce1c1281c6c8da0423c83b6e"}, - {file = "grpcio-1.80.0-cp314-cp314-win32.whl", hash = "sha256:367ce30ba67d05e0592470428f0ec1c31714cab9ef19b8f2e37be1f4c7d32fae"}, - {file = "grpcio-1.80.0-cp314-cp314-win_amd64.whl", hash = "sha256:3b01e1f5464c583d2f567b2e46ff0d516ef979978f72091fd81f5ab7fa6e2e7f"}, - {file = "grpcio-1.80.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:aacdfb4ed3eb919ca997504d27e03d5dba403c85130b8ed450308590a738f7a4"}, - {file = "grpcio-1.80.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:a361c20ec1ccd3c3953d20fb6d7b4125093bdd10dff44c5e2bbb39e58917cedc"}, - {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:43168871f170d1e4ed16ae03d10cd21efa29f190e710a624cee7e5ae07da6f4f"}, - {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1b97cd29a8eda100b559b455331c487a80915b6ea6bd91cf3e89836c4ee8d957"}, - {file = "grpcio-1.80.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bac1d573dfa84ce59a5547073e28fa7326d53352adda6912e362da0b917fcef4"}, - {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4560cf0e86514595dbbd330cd65b7afad4b5c4b8c4905c041cfffa138d45e6fd"}, - {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec0a592e926071b4abad50c1495cd0d0d513324b3ff5e7267067c33ba27506e4"}, - {file = "grpcio-1.80.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:deb10a1528473c11f72a0939eed36d83e847d7cbb63e8cc5611fb7a912d38614"}, - {file = "grpcio-1.80.0-cp39-cp39-win32.whl", hash = "sha256:627fb7312171cdc52828bd6fac8d7028ff2a64b89f1957b6f3416caa2218d141"}, - {file = "grpcio-1.80.0-cp39-cp39-win_amd64.whl", hash = "sha256:05d55e1798756282cddd52d56c896b3e7d673e3a8798c2f1cd05ba249a3bb4de"}, - {file = "grpcio-1.80.0.tar.gz", hash = "sha256:29aca15edd0688c22ba01d7cc01cb000d72b2033f4a3c72a81a19b56fd143257"}, + {file = "grpcio-1.83.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:fba099b716e73512d61b97f71ea3c31a72abb36904036e316bf4dd148ca8dcc8"}, + {file = "grpcio-1.83.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:6755ed67cc3e454d51ae9f6e1915b80d3942fa4de956ef48dacd45ab7f40b727"}, + {file = "grpcio-1.83.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5882c1a721b50ce0123ee5e839e1ab059ad72a7ade76cdf2d5bd833b56791acf"}, + {file = "grpcio-1.83.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4e3eedfc92b6b9f2960115e7e620cf0cbf80bb7849a51ce3820dc54dfd88b6b9"}, + {file = "grpcio-1.83.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4fcaa7c45c45b4a89e2867d1f1785d9481a788399d915e341ed2eb49aeef9dd4"}, + {file = "grpcio-1.83.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6b6c666a1d5613ff360c9e90f44665e3a88b25a815209ddbc0917eec281931cb"}, + {file = "grpcio-1.83.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6be5c807b717be3dd649446f021301fd7907e376318675d2147823071034112a"}, + {file = "grpcio-1.83.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c834e86d8fd2f03d7e4db49a027f7c5b89c5b88eed305543a5295bd6fee61e40"}, + {file = "grpcio-1.83.0-cp310-cp310-win32.whl", hash = "sha256:35a5b1c192496b6c25956eebfa963468935612206fd2543ac3ce981e6a5e0f03"}, + {file = "grpcio-1.83.0-cp310-cp310-win_amd64.whl", hash = "sha256:8f6c395e493d20c39b29392ca200e9aaeb78d0bc2f04db0c0a7da7ddc939aa57"}, + {file = "grpcio-1.83.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:8ff0b8767ddd62704e0d9571c1890af08d84a3a689ebba1807e62519d0b3277f"}, + {file = "grpcio-1.83.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:4772402f43517b4824980be4b3b2274a81eec0004a70009473c31b340d43e223"}, + {file = "grpcio-1.83.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f4cee5fc86e84a0cf7ad1574b454c3320e087c07f55b7df5dc0ac6a873fb90c0"}, + {file = "grpcio-1.83.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f5e822a7e7d03282f6ad225e710493c48b9057a353358344a5f7c42b2b37618d"}, + {file = "grpcio-1.83.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f5f410d7c2903eabb34789dfd6342eef04af1ad459943936b7e09a9f5bd417b9"}, + {file = "grpcio-1.83.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee94a4016fdf8699fb1fd8a38652475ff677f1c72074cee44deeeb9a7e95e745"}, + {file = "grpcio-1.83.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c6444666317338e903093c7c756e6cc88eee59f798cb8dd41e87725bf54e1617"}, + {file = "grpcio-1.83.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:aa074041231f03959cb097dd5517b0677b8ea49215bae01d5710a7b69dd59969"}, + {file = "grpcio-1.83.0-cp311-cp311-win32.whl", hash = "sha256:cb056f6e171c42639a50460b2929c82241fda51f71cf3dcdd68090fe45095a45"}, + {file = "grpcio-1.83.0-cp311-cp311-win_amd64.whl", hash = "sha256:7416952ca770477990257206276999056f8316d79196f2f25942393e58a20b49"}, + {file = "grpcio-1.83.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:28f6c35ac8fcf10e4594f138e468f194360089dde40d126a7033e863fc479930"}, + {file = "grpcio-1.83.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:33898e6a28e4ae598f1577cb1c4fec2a15c033d0ec52b9b45a09610dd045b9da"}, + {file = "grpcio-1.83.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6fb8a1dd0c6f0f931e69e9d0dc6d1c406ed2a44fa963414eafba07b7fb685d16"}, + {file = "grpcio-1.83.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2b5e75c34842cd9c1b95285ca395c6a569664b81e3ffa6b714125922942abaaf"}, + {file = "grpcio-1.83.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeb339838db07600481ef869507279b75326c75eac6d10f7afa62a0da1d2bcdd"}, + {file = "grpcio-1.83.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f47d62808b4c0a97b78bff88a6d4ca283a2a492b9a04a87d814af95ca3b9c19c"}, + {file = "grpcio-1.83.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62003babc444a606dcd1f009cd16391ce23669ae4ad6ec267a873da7937a69f5"}, + {file = "grpcio-1.83.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1aa567f8c3f19850ffd5d2858c9a8ea7c80f0db6c01186b71eb31e923ec984f5"}, + {file = "grpcio-1.83.0-cp312-cp312-win32.whl", hash = "sha256:cb2906c61db4f9c64cc360054b5df70eeb81846228e9e56a4944bd415a63dadc"}, + {file = "grpcio-1.83.0-cp312-cp312-win_amd64.whl", hash = "sha256:1c699bbb20f143c8f2bff219de578aa2dc1f919399d67dc702b038b986ee62df"}, + {file = "grpcio-1.83.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:6662f3b1e07cc7493d437351860dc867bddc6a93c83ecf33bbfdaf0c217ab2d0"}, + {file = "grpcio-1.83.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:74fe6f9e8a35c7dbf32255ee154d15e3e5338a81ed39173d079d594d2e544cd1"}, + {file = "grpcio-1.83.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:10b3fa0475eb572c9a81a6fe37fa16a9c500c0c91cfc148cac15692b7e3c2867"}, + {file = "grpcio-1.83.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:5f20a988480b0f28207f057f7f7ae1313393c3cef0adcfeae8248f9947eaf881"}, + {file = "grpcio-1.83.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7bd82671b39065ba18cd536e9cd45b27ff649053f81ddd2c6a966d595067080f"}, + {file = "grpcio-1.83.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc60215b5cb9fc8ca72942c498b551ac2305bd08f6ef8d4e3f0d21b64fbecd61"}, + {file = "grpcio-1.83.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f1c3e5689d4b90987b1d72022bcfe866a9a3dc66197484cf856d96b6150e7f45"}, + {file = "grpcio-1.83.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a21cb4eeeba124443f399be2e8b624943cde864dcbe588cb42e5c483a52a906c"}, + {file = "grpcio-1.83.0-cp313-cp313-win32.whl", hash = "sha256:8fe04f1050a59f875601eb55d42b4f66946fe89817f967e34db1462ccd07dadf"}, + {file = "grpcio-1.83.0-cp313-cp313-win_amd64.whl", hash = "sha256:6e01ecd9d8ef280abe1365138a4dc318f9a5287f4cb1b41d07816f796653f735"}, + {file = "grpcio-1.83.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:3f351629f6ae16ecc0ec3553e586a6763ffd9f6114044286d0cbec3e09241bfa"}, + {file = "grpcio-1.83.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:d05ff664100d429335b93c91b8b34ddf9e94a112205e7fa06dede309e44a4e4c"}, + {file = "grpcio-1.83.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7936f2a56cf04f6514705c0fedf400971de01b6aa1719327e4718f410a765e2b"}, + {file = "grpcio-1.83.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b0a0be840e51b6b7ee9df9269770faf77bdf4b771053c257c21d12bad607714c"}, + {file = "grpcio-1.83.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:009667eaf3dcd5224c713589cdc98e7ca4ed0ff0b61132c6b276e930eb83a2df"}, + {file = "grpcio-1.83.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bb669918fd88936b15599caff4160a77ab74bdeb25f2231f6e45b61282d6107b"}, + {file = "grpcio-1.83.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c19b454d3d3f28db81f2c7c4dbaee96e7f6fd149721733ffe79d6bc530f17404"}, + {file = "grpcio-1.83.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:61007cd08640abc5c54547ee32505474c482cd733a53cb87551ea81faa6350af"}, + {file = "grpcio-1.83.0-cp314-cp314-win32.whl", hash = "sha256:32e11c37f5285b0c6fa3042c05fe06903696689749833fc64e67dec71b9bbe33"}, + {file = "grpcio-1.83.0-cp314-cp314-win_amd64.whl", hash = "sha256:2bb48cb5e6dd005ca12b89ce4b6ac0b48ff3112c747542ee7986ef611a8ca6d9"}, + {file = "grpcio-1.83.0.tar.gz", hash = "sha256:7674587248fbbb2ac6e4eecf83a8a0f3d91a928f941de571acfd3a2f007fbc24"}, ] [package.dependencies] typing-extensions = ">=4.12,<5.0" [package.extras] -protobuf = ["grpcio-tools (>=1.80.0)"] - -[[package]] -name = "grpcio-status" -version = "1.71.2" -description = "Status proto mapping for gRPC" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "grpcio_status-1.71.2-py3-none-any.whl", hash = "sha256:803c98cb6a8b7dc6dbb785b1111aed739f241ab5e9da0bba96888aa74704cfd3"}, - {file = "grpcio_status-1.71.2.tar.gz", hash = "sha256:c7a97e176df71cdc2c179cd1847d7fc86cca5832ad12e9798d7fed6b7a1aab50"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.71.2" -protobuf = ">=5.26.1,<6.0.dev0" +protobuf = ["grpcio-tools (>=1.83.0)"] [[package]] name = "gunicorn" @@ -2417,38 +2292,30 @@ files = [ [[package]] name = "hf-xet" -version = "1.4.3" +version = "1.5.2" description = "Fast transfer of large files with the Hugging Face Hub." optional = false python-versions = ">=3.8" groups = ["main"] markers = "python_version < \"3.14\" and (platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\")" files = [ - {file = "hf_xet-1.4.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:7551659ba4f1e1074e9623996f28c3873682530aee0a846b7f2f066239228144"}, - {file = "hf_xet-1.4.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bee693ada985e7045997f05f081d0e12c4c08bd7626dc397f8a7c487e6c04f7f"}, - {file = "hf_xet-1.4.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21644b404bb0100fe3857892f752c4d09642586fd988e61501c95bbf44b393a3"}, - {file = "hf_xet-1.4.3-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:987f09cfe418237812896a6736b81b1af02a3a6dcb4b4944425c4c4fca7a7cf8"}, - {file = "hf_xet-1.4.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:60cf7fc43a99da0a853345cf86d23738c03983ee5249613a6305d3e57a5dca74"}, - {file = "hf_xet-1.4.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2815a49a7a59f3e2edf0cf113ae88e8cb2ca2a221bf353fb60c609584f4884d4"}, - {file = "hf_xet-1.4.3-cp313-cp313t-win_amd64.whl", hash = "sha256:42ee323265f1e6a81b0e11094564fb7f7e0ec75b5105ffd91ae63f403a11931b"}, - {file = "hf_xet-1.4.3-cp313-cp313t-win_arm64.whl", hash = "sha256:27c976ba60079fb8217f485b9c5c7fcd21c90b0367753805f87cb9f3cdc4418a"}, - {file = "hf_xet-1.4.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5251d5ece3a81815bae9abab41cf7ddb7bcb8f56411bce0827f4a3071c92fdc6"}, - {file = "hf_xet-1.4.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1feb0f3abeacee143367c326a128a2e2b60868ec12a36c225afb1d6c5a05e6d2"}, - {file = "hf_xet-1.4.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8b301fc150290ca90b4fccd079829b84bb4786747584ae08b94b4577d82fb791"}, - {file = "hf_xet-1.4.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d972fbe95ddc0d3c0fc49b31a8a69f47db35c1e3699bf316421705741aab6653"}, - {file = "hf_xet-1.4.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c5b48db1ee344a805a1b9bd2cda9b6b65fe77ed3787bd6e87ad5521141d317cd"}, - {file = "hf_xet-1.4.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:22bdc1f5fb8b15bf2831440b91d1c9bbceeb7e10c81a12e8d75889996a5c9da8"}, - {file = "hf_xet-1.4.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0392c79b7cf48418cd61478c1a925246cf10639f4cd9d94368d8ca1e8df9ea07"}, - {file = "hf_xet-1.4.3-cp314-cp314t-win_arm64.whl", hash = "sha256:681c92a07796325778a79d76c67011764ecc9042a8c3579332b61b63ae512075"}, - {file = "hf_xet-1.4.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:d0da85329eaf196e03e90b84c2d0aca53bd4573d097a75f99609e80775f98025"}, - {file = "hf_xet-1.4.3-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:e23717ce4186b265f69afa66e6f0069fe7efbf331546f5c313d00e123dc84583"}, - {file = "hf_xet-1.4.3-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc360b70c815bf340ed56c7b8c63aacf11762a4b099b2fe2c9bd6d6068668c08"}, - {file = "hf_xet-1.4.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39f2d2e9654cd9b4319885733993807aab6de9dfbd34c42f0b78338d6617421f"}, - {file = "hf_xet-1.4.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:49ad8a8cead2b56051aa84d7fce3e1335efe68df3cf6c058f22a65513885baac"}, - {file = "hf_xet-1.4.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7716d62015477a70ea272d2d68cd7cad140f61c52ee452e133e139abfe2c17ba"}, - {file = "hf_xet-1.4.3-cp37-abi3-win_amd64.whl", hash = "sha256:6b591fcad34e272a5b02607485e4f2a1334aebf1bc6d16ce8eb1eb8978ac2021"}, - {file = "hf_xet-1.4.3-cp37-abi3-win_arm64.whl", hash = "sha256:7c2c7e20bcfcc946dc67187c203463f5e932e395845d098cc2a93f5b67ca0b47"}, - {file = "hf_xet-1.4.3.tar.gz", hash = "sha256:8ddedb73c8c08928c793df2f3401ec26f95be7f7e516a7bee2fbb546f6676113"}, + {file = "hf_xet-1.5.2-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:4a5ecb9cda8512ba2aa8ee5d37c87a1422992165892d653098c7b90247481c3b"}, + {file = "hf_xet-1.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8764488197c1d7b1378c8438c18d2eea902e150dbca0b0f0d2d32603fb9b5576"}, + {file = "hf_xet-1.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8d7446f72abbf7e01ca5ff131786bc2e74a56393462c17a6bf1e303fbab81db4"}, + {file = "hf_xet-1.5.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:580e59e29bf37aece1f2b68537de1e3fb04f43a23d910dcf6f128280b5bfbba4"}, + {file = "hf_xet-1.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bee28c619622d36968056532fd49cf2b35ca75099b1d616c31a618a893491380"}, + {file = "hf_xet-1.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e396ab0faf6298199ad7a95305c3ca8498cb825978a6485be6d00587ee4ec577"}, + {file = "hf_xet-1.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:fd3add255549e8ef58fa35b2e42dc016961c050600444e7d77d030ba6b57120e"}, + {file = "hf_xet-1.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d6f9c58549407b84b9a5383afd68db0acc42345326a3159990b36a5ca8a20e4e"}, + {file = "hf_xet-1.5.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f922b8f5fb84f1dd3d7ab7a1316354a1bca9b1c73ecfc19c76e51a2a49d29799"}, + {file = "hf_xet-1.5.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:045f84440c55cdeb659cf1a1dd48c77bcd0d2e93632e2fea8f2c3bdee79f38ed"}, + {file = "hf_xet-1.5.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db78c39c83d6279daddc98e2238f373ab8980685556d42472b4ec51abcf03e8c"}, + {file = "hf_xet-1.5.2-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7db73c810500c54c6760be8c39d4b2e476974de85424c50063efc22fdda13025"}, + {file = "hf_xet-1.5.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6395cfe3c9cbead4f16b31808b0e67eac428b66c656f856e99636adaddea878f"}, + {file = "hf_xet-1.5.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:cde8cd167126bb6109b2ceb19b844433a4988643e8f3e01dd9dd0e4a34535097"}, + {file = "hf_xet-1.5.2-cp38-abi3-win_amd64.whl", hash = "sha256:ecf63d1cb69a9a7319910f8f83fcf9b46e7a32dfcf4b8f8eeddb55f647306e65"}, + {file = "hf_xet-1.5.2-cp38-abi3-win_arm64.whl", hash = "sha256:1da28519496eb7c8094c11e4d25509b4a468457a0302d58136099db2fd9a671d"}, + {file = "hf_xet-1.5.2.tar.gz", hash = "sha256:73044bd31bae33c984af832d19c752a0dffb67518fee9ddbd91d616e1101cf47"}, ] [package.extras] @@ -2456,14 +2323,14 @@ tests = ["pytest"] [[package]] name = "holidays" -version = "0.100" +version = "0.101" description = "Open World Holidays Framework" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "holidays-0.100-py3-none-any.whl", hash = "sha256:cf67e8983c3af182b62081be27c965c6fdf41377026aa62ac82d1bbc8c7ebd8f"}, - {file = "holidays-0.100.tar.gz", hash = "sha256:76e963cd17758ba0e0519daff725f676eaebeda71e500cd235f647307be31e31"}, + {file = "holidays-0.101-py3-none-any.whl", hash = "sha256:be1d5bb0b662d709da08dcdfa9b42feb678312df2a5d6280421da71349e4757f"}, + {file = "holidays-0.101.tar.gz", hash = "sha256:fbaa802d66e5d24877359ae68c46d00a73437162d3e9a17466fe6cfcce123c3a"}, ] [package.dependencies] @@ -2493,14 +2360,14 @@ trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httplib2" -version = "0.31.2" +version = "0.32.0" description = "A comprehensive HTTP client library." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "httplib2-0.31.2-py3-none-any.whl", hash = "sha256:dbf0c2fa3862acf3c55c078ea9c0bc4481d7dc5117cae71be9514912cf9f8349"}, - {file = "httplib2-0.31.2.tar.gz", hash = "sha256:385e0869d7397484f4eab426197a4c020b606edd43372492337c0b4010ae5d24"}, + {file = "httplib2-0.32.0-py3-none-any.whl", hash = "sha256:dc6705cacdf3fb0a2aba7629fa33c90fd93e30035db0c157325826be177e4816"}, + {file = "httplib2-0.32.0.tar.gz", hash = "sha256:48a0ef30a42db65d8f3399045e1d09ab0ba66e3b9efc360d07f80ea55d286025"}, ] [package.dependencies] @@ -2545,26 +2412,26 @@ files = [ [[package]] name = "huggingface-hub" -version = "1.13.0" +version = "1.25.1" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = false python-versions = ">=3.10.0" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "huggingface_hub-1.13.0-py3-none-any.whl", hash = "sha256:e942cb50d6a08dd5306688b1ac05bda157fd2fcc88b63dae405f7bd0d3234005"}, - {file = "huggingface_hub-1.13.0.tar.gz", hash = "sha256:f6df2dac5abe82ce2fe05873d10d5ff47bc677d616a2f521f4ee26db9415d9d0"}, + {file = "huggingface_hub-1.25.1-py3-none-any.whl", hash = "sha256:004d4e70350517e24c68a7dbb7dc5e40b2b6aefef8f94bf7a85f6f9835102ea5"}, + {file = "huggingface_hub-1.25.1.tar.gz", hash = "sha256:21129595ca7a753be479b319913e22cc8808361ac118bd76cc413db831b28a99"}, ] [package.dependencies] +click = ">=8.4.2,<9.0.0" filelock = ">=3.10.0" fsspec = ">=2023.5.0" -hf-xet = {version = ">=1.4.3,<2.0.0", markers = "platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\""} +hf-xet = {version = ">=1.5.1,<2.0.0", markers = "platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\""} httpx = ">=0.23.0,<1" packaging = ">=20.9" pyyaml = ">=5.1" tqdm = ">=4.42.1" -typer = "*" typing-extensions = ">=4.1.0" [package.extras] @@ -2572,7 +2439,7 @@ all = ["Jinja2", "Pillow", "authlib (>=1.3.2)", "duckdb", "fastapi", "fastapi", dev = ["Jinja2", "Pillow", "authlib (>=1.3.2)", "duckdb", "fastapi", "fastapi", "httpx", "itsdangerous", "jedi", "libcst (>=1.4.0)", "mypy (==1.15.0)", "numpy", "pytest (>=8.4.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures (<16.0)", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "ty", "types-PyYAML", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] gradio = ["gradio (>=5.0.0)", "requests"] -hf-xet = ["hf-xet (>=1.4.3,<2.0.0)"] +hf-xet = ["hf-xet (>=1.5.1,<2.0.0)"] mcp = ["mcp (>=1.8.0)"] oauth = ["authlib (>=1.3.2)", "fastapi", "httpx", "itsdangerous"] quality = ["libcst (>=1.4.0)", "mypy (==1.15.0)", "ruff (>=0.9.0)", "ty"] @@ -2680,7 +2547,6 @@ description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" groups = ["main"] -markers = "python_version < \"3.14\"" files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -2694,121 +2560,117 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jiter" -version = "0.15.0" +version = "0.16.0" description = "Fast iterable JSON parser." optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "jiter-0.15.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:edebcf7d1f601199084bb6e844d7dc67e03e04f6ac786b0332d616635c4ff7a4"}, - {file = "jiter-0.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f924585cdacf631cd382b657966847bb537bf9ed0a6f9b991da5f05a631480f"}, - {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abbf258599526ad0326fe51e252e24f2bd6f24f1852681b4b78feda3808f1d18"}, - {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c468136b8bd6bb18c8786e4236a1fa27362f24cb23450ba0cb204ab379b8e6f"}, - {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05906b93d72f03339e6bb7cf8dc10ebda64a0266126eed6beba79e20abcf5fd4"}, - {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30ce785d2adb8e32c3f7741442370a74834ec4c01f3c48f0750227a0b4ef27d6"}, - {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd73e3da91a0a722d67165e849ce2cdc10de0e0d48738c142be8c6c5f310f4c"}, - {file = "jiter-0.15.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:ceb8fc27d38793f9c97149be8302720c5b22e5c195a37bf2c45dc36c4600a512"}, - {file = "jiter-0.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d726e3ceeb337191324b49de298142f27c3ad10886341555d1d5315b5f252c6a"}, - {file = "jiter-0.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2c8aea7781d2a372227871de4e1a1332aa96f5a89fd76c5e835dafdbad102887"}, - {file = "jiter-0.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cf4bd113a69c0a740e27cb962ce10630c36d2b8f59d759a651b955ee9d18a823"}, - {file = "jiter-0.15.0-cp310-cp310-win32.whl", hash = "sha256:d92a5cd21fdb083931d546c207aa29633787c5dc5b02daab2d32b843f88a2c53"}, - {file = "jiter-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:e58585a58209d72691ce2d62a9147445f5a87beb0bde97fde284c96ae392a3d1"}, - {file = "jiter-0.15.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0f862193b8696249d22ec433e85fd2ab0ad9596bc3e45e6c0bc55e8aeba97be2"}, - {file = "jiter-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1303d4d68a9b051ea90502402063ecf3807da00ad2affa19ca1ae3b90b3c5f67"}, - {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392b8ab019e5502d08aff85c6272209c24bc2cbe706ea82a56368f524236614a"}, - {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:773b6eb282ce11ee19f05f6b2d4404fa308e5bbd353b0b80a0262caad6db2cd7"}, - {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2c0c44d569ce0f2850f5c926f8caeb5f245fbc84475aeb36efccc2103e6dbd"}, - {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:032396229564bca02440396bd327710719f724f5e7b7e9f7a8eb3faa4a2c2281"}, - {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d37768fce7f88dd2a8c6091f2325dea27d30d30d5c6e7a1c0f0af77723b708"}, - {file = "jiter-0.15.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:2c9cb907439d20bd0c7d7565ca01ee52234203208433749bae5b516907526928"}, - {file = "jiter-0.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9100ddbec09741cc66feb0fc6773f8bdbd0e3c345689368f260082ff85dcc0cd"}, - {file = "jiter-0.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ae1b0d82ac2d987f9ea512b1c9adfcc71a28de3dea3a6039b54d76cffda9901e"}, - {file = "jiter-0.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8020c99ec13a7db2b6f96cbe82ef4721c88b426a4892f27478044af0284615ef"}, - {file = "jiter-0.15.0-cp311-cp311-win32.whl", hash = "sha256:42bfb257930800cf43e7c62c832402c704ab60797c992faf88d20e903eac8f32"}, - {file = "jiter-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:860a74063284a2ae9bfedd694f299cc2c68e2696c5f3d440cc9d18bb81b9dd04"}, - {file = "jiter-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:37a10c377ce3a4a85f4a67f28b7afe093154cde77eaf248a72e856aa08b4d865"}, - {file = "jiter-0.15.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0e90a1c315a0226ec822d973817967f9223b7701546c8c2a7913e7ab0926294d"}, - {file = "jiter-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c9004af7c8d67cce7f1aae1026fb55607f4aa600710d08ede3a3ce4aeefe7e0"}, - {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c210f8b35dc6f30aafd4b4365ca89b9d1189f21ab49b8e68fa6322a847aef138"}, - {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f30bae8bc1c2d613e28e5af3e8cceb09b742f1c8a8a5f839fb67afaffc03b61"}, - {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60e71b6d10cfc284c9bf36bd885e8d44c46f688ce50aa91b5edd90181dea687"}, - {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ab068bce62a45aa3e7367eceaffb5dde60b7eb853be8dece45132e3d0ff4879"}, - {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa248c9eb220197d363f688818dac2fd4b2f0cd7d843ca7105d652034823427d"}, - {file = "jiter-0.15.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2a77aadd57cac1682e4401a72724d2796d89a4ba129b1a5812aa94ee480826eb"}, - {file = "jiter-0.15.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ae901f3a55bfafdde31d289590fa25e3245735a2b1e8c7cc15871710a002871"}, - {file = "jiter-0.15.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f0b271b462769543716f92d3a4f90527df6ef5ed05ee95ec4137f513e21e1b77"}, - {file = "jiter-0.15.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2fb6a5d26af81fc0f00f9360a891e05cf755e149bba391c4d563adc54812973d"}, - {file = "jiter-0.15.0-cp312-cp312-win32.whl", hash = "sha256:c2f6bb8b5216ab9e7873bc08b5d7bef2b8abbb578a3069bf1cd14a45d71d771d"}, - {file = "jiter-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:40b2c7e92c44a84d748d21706c68dc6ff8161d80b59c99d774721a0d2317d7c7"}, - {file = "jiter-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:cc0bc345cf2df9d1c00ac443f50d543c1ccfa8b0422cb85b1ab70d681c0b255b"}, - {file = "jiter-0.15.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1c11465f97e2abf45a014b83b730222f8f1c5335e802c7055a67d50de6f1f4e3"}, - {file = "jiter-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e7b1776f0797956c509e123d0952d10d293a9492dea9f288ab9570ec01d1a5"}, - {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:351a341c2105aa430b7047e30f1bf7975f6313b00165d3fc07be2edaf741f279"}, - {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ab395feec8d249ec4044e228e98a7033f043426a265df439dc3698823f0a4e4"}, - {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2a438005b6f22d0273413484d6094d7c2c5d10ec1b3a3bf128e0d1d3ba53258"}, - {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f18f85e4218d1b40f000f42a92239a7a61a902cd42c65e6c360dbd17dcb20894"}, - {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1aa62e277fc1cbd80e6deacae6f4d983b41b3d7728e0645c5d741a6149bba45"}, - {file = "jiter-0.15.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:6550fa135c7deb8ead6af49ed7ff648532ea8334a1447fe34a36315ef79c5c29"}, - {file = "jiter-0.15.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:066f8f33f18b2419cd8213b2436fa7fbc9c499f315971cfa3ce1f9820c001b1b"}, - {file = "jiter-0.15.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:75e8a04e91432dde9f1838373cf93d23726c79d3e908d319acf0e796f85592e7"}, - {file = "jiter-0.15.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a97261f1fccb8e50ecd2890a96e46efdc3f57c80a197324c6777827231eca712"}, - {file = "jiter-0.15.0-cp313-cp313-win32.whl", hash = "sha256:c77496cb10bd7549690fbbab3e5ec05857b83e49276f4a9423a766ddd2afcd4c"}, - {file = "jiter-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b15741f501469009ae0ae90b7147958a664a7dede40aa7ff174a8a4645f546d0"}, - {file = "jiter-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d6a60072b44c3c2b797a7ddcbcbbf2b34ea3cfd4721580fbfd2a09d9d9b84ba"}, - {file = "jiter-0.15.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ef1fd24d9413f6209e00d3d5a453e67acfe004a25cc6c8e8484faed4311ab9e8"}, - {file = "jiter-0.15.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:144f8e72cb53dab146347b91cceac01f5481237f2b93b4a339a1ee8f8878b67c"}, - {file = "jiter-0.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553fcac2ef2cb990877f9fc0833b8b629a3e6a5670b6b5fd58219b41a653ddc4"}, - {file = "jiter-0.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:774f93f65031856bf14ad9f59bdcab8b8cad501e5ceabd51ba3525f76937a25b"}, - {file = "jiter-0.15.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f1e1754960f38ec40613a07e5e372df67acb3b890fb383b6fb3de3e49ddbf3c7"}, - {file = "jiter-0.15.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:ac0d9ddea4350974be7a221fc25895f251a8fee748c889bdced2141c0fec1a49"}, - {file = "jiter-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:01a8222cf05ab1128e239421156c207949808acaaea2bdfd33130ae666786e86"}, - {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:182226cbc930c9fab81bc2e41a4da672f89539906dadb05e75670ac07b94f71f"}, - {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71683c38c825452999b5717fcae07ea708e8c93003e808be4319c1b02e3d176e"}, - {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f2218e6a9e5c18bc10fe6d41ac189c442c88eacf11bad9f28ef95a9bef00e6"}, - {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5157de9f76eb4bc5ea74a1219366a25f945ad305641d74e04f59c54087091aa9"}, - {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c5db5527c221249a876160663ab891ace358c17f7b9c93ec1478b7f0550e5c"}, - {file = "jiter-0.15.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:3e4540b8e74e4268811ac05db226a6a128ff572e7e0ce3f1163b693cadb184cd"}, - {file = "jiter-0.15.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:62ebd14e47e9aed9df4472afcb2663668ce4d74891cd54f86bf6e44029d6dc89"}, - {file = "jiter-0.15.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0be6f5ad41a809f303f416d17cec92a7a725902fb9b4f3de3d19362ac0ef8554"}, - {file = "jiter-0.15.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:813dfbb17d65328bf86e5f0905dd277ba2265d3ca20556e86c0c7035b7182e5a"}, - {file = "jiter-0.15.0-cp314-cp314-win32.whl", hash = "sha256:50e51156192722a9c58db112837d3f8ef96fb3c5ecc14e95f409134b08b158ec"}, - {file = "jiter-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:30ce1a5d16b5641dc935d50ef775af6a0871e3d14ab05d6fc54dff371b78e558"}, - {file = "jiter-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:510c8b3c17a0ed9ac69850c0438dada3c9b82d9c4d589fcb62002a5a9cf3a866"}, - {file = "jiter-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7553333dd0930c104a5a0db8df72bf7219fe663d731383b576bb6ed6351c984d"}, - {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2143ab06181d2b029eedcb6af3cebe95f11bbac62441781860f98ee9330a6a6"}, - {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eac374c5c975709b69c10f09afd199df74150172156ad10c8d4fd785b7da995"}, - {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3b3b775e33d3bfaec9899edc526ae97b0da0bf9d071a46124ba419149a414f8"}, - {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3071db3346334beae1360b46da4606da57bf3528c167b3c38533afaf9f2c5"}, - {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6694a173ecabc12eb60efbc0b474464ead1951ff65cd8b1e72100715c64512b"}, - {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:a254e10b593624d230c365b6d616b22ca0ad65e63a16e6631c2b3466022e6ba8"}, - {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d8d2955167274e15d79a7a020afdd9b39c990eb80b2d89fca695d92dcfdd38ec"}, - {file = "jiter-0.15.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:acf4ee4d1fc55917239fe72972fb292dd773055d05eb040d36f4326e02cc2c0e"}, - {file = "jiter-0.15.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:e7196e56f1cd69af1dbb07dff02dcfb260a50b45a82d409d92a06fedb32473b5"}, - {file = "jiter-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:7f6163c0f10b055245f814dcc59f4818da60dfe72f3e72ab89fc24b6bd5e9c52"}, - {file = "jiter-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:980c256edb05b78a111b99c4de3b1d32e31634b867fd1fc2cf726e7b7bba9854"}, - {file = "jiter-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:66b1880df2d01e206e8339769d1c7c1753bcb653efd6289e203f6f24ebada0c0"}, - {file = "jiter-0.15.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:04b400bbf8c9efb03d9bdd976475c919c1d85593b04b9fff7ae234065daf87ae"}, - {file = "jiter-0.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25ffbe229aa8cd98c28879d8aa1a6e34ae77992ab984a65fba800859dab16269"}, - {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5607e6013ed7e6b0ec9661e467b7ffde0aa7ab36833a04850f26fcf88ed4845b"}, - {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50164d7610c00e7cd913a873fce30b6beeebf4b37e53983e33f22de4c900f6b8"}, - {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab596fa3837e91e7e6a31b5f639988bfc6a35d1f915ac3932d946062219d588f"}, - {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72d8af5c1013656a8870c866660627d1a75bc185814ee022c8533caa1de88ae"}, - {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c84c1b7be454b0c16f8499b4ebfbfd82ea5cca6527cceefcbbc06a7557b5ed2e"}, - {file = "jiter-0.15.0-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:d636d5095155afd364247f65070fab7beda13498d7ff4de331046e704ab9657f"}, - {file = "jiter-0.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7d3d6683288c11cbab50e865f2e2f13950179aa45410e30b2cfbd3fb7b0177bf"}, - {file = "jiter-0.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7ce8902f939970048b233087082e7bb829db29375811c7ad50687b8624c6fd08"}, - {file = "jiter-0.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4363818355dbc70ae1a8e9eaba9de350d93ede4ff6992b8f8eb8cbb6e5122d42"}, - {file = "jiter-0.15.0-cp39-cp39-win32.whl", hash = "sha256:8f7e9bc0f1135039b22ee6eab588d42df1ce55842b30740a352885eb267bd941"}, - {file = "jiter-0.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:1c15024a3d892223b18f597c86d59387249dc396590844ce6b9f6131d1093bae"}, - {file = "jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:411fa4dfa5a7ae3d11491027ffb9beadec3996010a986862db70d91abba1c750"}, - {file = "jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:2b0074e2f56eb2dacca1689760fd2852a068f85a0547a157b82cb4cafeb6768b"}, - {file = "jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:913d02d29c9606643418d9ccfc3b72492ab25a6bf7889934e09a3490f8d3438b"}, - {file = "jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b15d3ec9b0449c40e85319bdb4caa8b77ab526e74f5532ed94bec15e2f66822c"}, - {file = "jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:631f13a3d04e97d4e083993b10f4b99530e3a10d953e2eb5e196b7dc7f812ce0"}, - {file = "jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:b6c0ffae686c39bf3737be60793783267628783ea42545632c10b291105aee45"}, - {file = "jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d54fb5b31dea401a41af3f8a7d2512e9b6a6a005491e6166c7e4ffab9639a9c"}, - {file = "jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d5d6090cdc1b7c9e780dfb04949a990adb1e301a2fc0bbcee7de4638d33f9a"}, - {file = "jiter-0.15.0.tar.gz", hash = "sha256:4251acc80e2b7c9b7b8823456ea0fceeb0734dac2df7636d3c711b38476b5a76"}, + {file = "jiter-0.16.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c5fc4f8def331036a7b8e981b4347ebe409981edbc8308a5ea842b8c3614fa6c"}, + {file = "jiter-0.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5a71d0d2014c3275043e1170bf3d4e771493cb0dcf07be54c567155f4d8ee64b"}, + {file = "jiter-0.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:741eed508c233a76313a1c7b001f8f21b82f14327e9196ae8bd29a2cc164ae84"}, + {file = "jiter-0.16.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3fb7bc819187b56dc48aa5c833aaf92257da8e07efdb9306156667bd2eeb491c"}, + {file = "jiter-0.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c9610fd25ebccb43fca584136f5c2fbb26802447eccd430dfdbab95a0fd5126"}, + {file = "jiter-0.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4a1d68ff7ca1d3b5dee20a97a3decda7d5f15003823bf6d140c81f8561d3bc5c"}, + {file = "jiter-0.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb08c276dd02dac3a284acdd02cacc630d2e3cd6572a4b85519f35cbd133c3de"}, + {file = "jiter-0.16.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:8fc4d94713c4697347e38faf7d6ef91547c142219bdcfc7220c4870879974244"}, + {file = "jiter-0.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a0f05e229edb29e68cdd0ccb83cea13b64263416120cf943767a6fd72e6787f"}, + {file = "jiter-0.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2c842cbf374a8daf50b2c04212995bee34ca2ac2cdc29a901b4cdb072c9c4131"}, + {file = "jiter-0.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5ed466aee31294d7cdcd4d37dfe5c42c97bc29d9a5f00eacf24504358309cb9b"}, + {file = "jiter-0.16.0-cp310-cp310-win32.whl", hash = "sha256:b42e9ff5376819c053da25809a8d4b6fa6e473b4856ebe42e298ac958be3d7f9"}, + {file = "jiter-0.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:10438939205546132189c8e74a2d536a707841f3a25cd7c74ee91fe503407a26"}, + {file = "jiter-0.16.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:67fddeda1688f0cce2d2ae83ccf8a80f79936f2d2997d6cc2261f82fdb54a4d3"}, + {file = "jiter-0.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c90c0f63df322be920eda6ce622e3083d8906ba267f8220fe7873213b8b4430e"}, + {file = "jiter-0.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64c0203212098470032aabcde9356fc168f377aade3e43def61dfe17e92f2037"}, + {file = "jiter-0.16.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12288303c9844e61e1651d02a9a6f6633e47d39f897d6991d1427161ce6b746e"}, + {file = "jiter-0.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cf109d010b4b05a105afb3d43be36a21322d345ad3111e13d15f680afef0e5b"}, + {file = "jiter-0.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62c1b7fe1f77925acf5af68b6140b8810fa87dfd4dc0a9c8568ec2fa2a10429c"}, + {file = "jiter-0.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8597d23c87f59294f83bcb6229b9ed1fccee13dbba967b46930d2f1759466fee"}, + {file = "jiter-0.16.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:3126a5dbad56401989ac769aca0cb56005bfb3e2366eea0ca99d1a91c3c1ee03"}, + {file = "jiter-0.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c4b4717bdb35ae456f831a6b08d01880fff399887a6bbc526a583a406e484eea"}, + {file = "jiter-0.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:adff21bc78edfe086c15eb495b900306076de378dc2337c132401fc39bd79c91"}, + {file = "jiter-0.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dab907db06fc593645e73109acf4581ba5b548897d28b9348dc41ddc8343b2d3"}, + {file = "jiter-0.16.0-cp311-cp311-win32.whl", hash = "sha256:560b2cf3fb03240cd34f27409a238547488708f05b7c3924f571a60422251ec7"}, + {file = "jiter-0.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:e431cfc9caf44c1d5459ff77d4e64cbf85fddb6a35dad836a15c6a9ec23087c1"}, + {file = "jiter-0.16.0-cp311-cp311-win_arm64.whl", hash = "sha256:2a8e9e39cf083016137aa5cadafe3188adc2ba6ba1fbf1e5d18889ad3e9ad056"}, + {file = "jiter-0.16.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:67c3bc1760f8c99d805dcab4e644027142a53b1d5d861f18780ebdbd5d40b72a"}, + {file = "jiter-0.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5af7780e4a26bd7d0d989592bf9ef12ebf806b74ab709223ecca37c749872ea9"}, + {file = "jiter-0.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5bf78d0e05e45cfdd66558893938d59afe3d1b1a824a202039b20e607d25a72"}, + {file = "jiter-0.16.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4444a83f946605990c98f625cdd3d2725bfb818158760c5748c653170a20e0e"}, + {file = "jiter-0.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a23f0e4f957e1be65752d2dfac9a5a06b1917af8dc85deb639c3b9d02e31290"}, + {file = "jiter-0.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c22a488f7b9218e245a0025a9ba6b100e2e54700831cf4cf16833a27fba3ad01"}, + {file = "jiter-0.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46add52f4ad47a08bfb1219f3e673da972191489a33016edefdb5ea55bfa8c48"}, + {file = "jiter-0.16.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:9c8a956fd72c2cf1e730d01ea080341f13aa0a97a4a33b51abebe725b7ae9ca9"}, + {file = "jiter-0.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:561926e0573ffe4a32498420a76d64b16c513e1ab413b9d28158a8764ac701e5"}, + {file = "jiter-0.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:44d019fa8cdaf89bf29c71b39e3712143fdd0ac76725c6ef954f9957a5ea8730"}, + {file = "jiter-0.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0df91907609837f33341b8e6fe73b95991fdaa57caf1a0fbd343dffe826f386f"}, + {file = "jiter-0.16.0-cp312-cp312-win32.whl", hash = "sha256:51d7b836acb0108d7c77df1742332cac2a1fa04a74d6dacec46e7091f0e91274"}, + {file = "jiter-0.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:1878349266f8ee36ecb1375cc5ba2f115f35fd9f0a1a4119e725e379126647f7"}, + {file = "jiter-0.16.0-cp312-cp312-win_arm64.whl", hash = "sha256:2ed5738ae4af18271a51a528b8811b0cbfa4a1858de9d83359e4169855d6a331"}, + {file = "jiter-0.16.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:41977aa5654023948c2dae2a81cbf9c43343954bef1cd59a154dd15a4d84c195"}, + {file = "jiter-0.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d28bb3c26762358dadf3e5bf0bccd29ae987d65e6988d2e6f49829c76b003c09"}, + {file = "jiter-0.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0542a7189c26920778658fc8fcf2af8bae05bae9924577f71804acef37996536"}, + {file = "jiter-0.16.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8fb8de1e23a0cb2a7f53c335049c7b72b6db41aa6227cdcc0972a1de5cb39450"}, + {file = "jiter-0.16.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b72d0b2990ca754a9102779ac98d8597b7cb31678958562214a007f909eab78e"}, + {file = "jiter-0.16.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5f91b1c27fc22a57993d5a5cb8a627cb8ed4b10502716fac1ffbfe1d19d84e8"}, + {file = "jiter-0.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c682bea068a90b764577bdb78a60a4c1d1606daf9cd4c893832a37c7cc9d9026"}, + {file = "jiter-0.16.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:8d031aabecc4f1b6276adfb42e3aabb77c89d468bf616600e8d3a11328929053"}, + {file = "jiter-0.16.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eab2cd170150e70153de16896a1774e3a1dca80154c56b54d7a812c479a7165e"}, + {file = "jiter-0.16.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:6edb63a46e65a82c26800a868e49b2cac30dd5a4218b88d74bc2c848c8ad60bb"}, + {file = "jiter-0.16.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:659039cc50b5addcc35fcc87ae2c1833b7c0a8e5326ef631a75e4478447bcf84"}, + {file = "jiter-0.16.0-cp313-cp313-win32.whl", hash = "sha256:c9c53be232c2e206ef9cdbad81a48bfa74c3d3f08bcf8124630a8a748aad993e"}, + {file = "jiter-0.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:baad945ed47f163ad833314f8e3288c396118934f94e7bbb9e243ce4b341a4fd"}, + {file = "jiter-0.16.0-cp313-cp313-win_arm64.whl", hash = "sha256:3c1fd2dbe1b0af19e987f03fe66c5f5bd105a2229c1aff4ab14890b24f41d21a"}, + {file = "jiter-0.16.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:b2c61484666ad42726029af0c00ef4541f0f3b5cdc550221f56c2343208018ee"}, + {file = "jiter-0.16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:63efadc657488f45db1c676d81e704cac2abf3fdb892def1faea61db053127e2"}, + {file = "jiter-0.16.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf0d73f50e7b6935677854f6e8e31d499ca7064dd24734f703e060f5b237d883"}, + {file = "jiter-0.16.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf3ea07d9bc8e7d03a9fbc051295462e6dbc295b894fd72457c3136e3e43d898"}, + {file = "jiter-0.16.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26798522707abb47d767db536e4148ceac1b14446bf028ee85e579a2e043cfe5"}, + {file = "jiter-0.16.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc837c1b9631be10abfe0191537fe8009838204cec7e44827401ace390ddb567"}, + {file = "jiter-0.16.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49060fd70737fad59d33ba9dcc0d83247dc9e77187de26053a19c16c9f32bd69"}, + {file = "jiter-0.16.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:adbb8edeadd431bc4477879d5d371ece7cb1334486584e0f252656dd7ffada29"}, + {file = "jiter-0.16.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:31aaee5b80f672c1dc21272bcfb9cbdcfc1ea04ff50f00ed5af500b80c44fa93"}, + {file = "jiter-0.16.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:6722bcef4ffc86c835574b1b2fac6b33b9fb4a889c781e67950e891591f3c55a"}, + {file = "jiter-0.16.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:5ab4f50ff971b611d656554ea10b75f80097392c827bc32923c6eeb6386c8b00"}, + {file = "jiter-0.16.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:710cc51d4ebdcd3c1f70b232c1db1ea1344a075770422bbd4bede5708335acbe"}, + {file = "jiter-0.16.0-cp314-cp314-win32.whl", hash = "sha256:57b37fc887a32d44798e4d8ebfa7c9683ff3da1d5bf38f08d1bb3573ccb39106"}, + {file = "jiter-0.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:cbd18dd5e2df96b580487b5745adf57ef64ad89ba2d9662fc3c19386acce7db8"}, + {file = "jiter-0.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:a32d2027a9fa67f109ff245a3252ece3ccc32cc56703e1deab6cc846a59e0585"}, + {file = "jiter-0.16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2577196f4474ef3fc4779a088a23b0897bbf86f9ea3679c372d45b8383b43207"}, + {file = "jiter-0.16.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e89e008a93c01104161c75b4988e58716b01d62307ebfe161e52a56d2a818"}, + {file = "jiter-0.16.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2e9efbe042210df657bade597f66d6d75723e3d8f45a12ea6d8167ff8bbce3"}, + {file = "jiter-0.16.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f4d9e473a5ce7d27fef8b848df4dc16e283893d3f53b4a585e72c9595f3c284"}, + {file = "jiter-0.16.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d30a4a1c87713060c8d1cc59a7b6c8fb6b8ef0a6900368014c76c87922a2929"}, + {file = "jiter-0.16.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae96332410f866e5900d809298b1ed82735932986c672495f9701daacd80620"}, + {file = "jiter-0.16.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:da3d7ec75dc83bb18bca888b5edfae0656a26849056c59e05a7728badd17e7af"}, + {file = "jiter-0.16.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ee6162b77d49a9939229df666dfa8af3e656b6701b54c4c84966d740e189264e"}, + {file = "jiter-0.16.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:63ffdbdae7d4499f4cda14eadc12ddcabef0fc0c081191bdc2247489cb698077"}, + {file = "jiter-0.16.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a111256a7193bea0759267b10385e5870949c239ed7b6ddbaaf57573edb38734"}, + {file = "jiter-0.16.0-cp314-cp314t-win32.whl", hash = "sha256:de5ba8763e56b793561f43bed197c9ea55776daa5e9a6b91eed68a909bc9cdbf"}, + {file = "jiter-0.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b8a3f9a6008048fe9def7bf465180564a6e458047d2ce499149cfbe73c3ae9db"}, + {file = "jiter-0.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0fa25b09b13075c46f5bc174f2690525a925a4fc2f7c82969a2bbabff22386ce"}, + {file = "jiter-0.16.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:d8f80521644426d451e70f00c7974240cab8f6ee088aedaa9af2697153ab7805"}, + {file = "jiter-0.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3b21b412b899fd8bd51a3046934b59a3bb068b79f70a5c6010053ac77cc53f0c"}, + {file = "jiter-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0758ab7747a984797cf048e8eedea1d8ef39d7994b25611daf5b48fc903e8873"}, + {file = "jiter-0.16.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9ec553a99b0987efd7a3645a1a825cf29c224e494db267a83369fcc8da9aeda5"}, + {file = "jiter-0.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3bd327cdfa118bc1ce69c214c2678571d5bd39b8ccd0ebf43a54db00541ba9a"}, + {file = "jiter-0.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26d122613ada2b708eb714695446f40fce5bdf2edb4b02116dec62faa62dfab3"}, + {file = "jiter-0.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e03a5f21a5ce96a9441b8cb32719a8b88ed5388f53e0f339c5bcf54f1317f9d0"}, + {file = "jiter-0.16.0-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:a5c54ef4ff776d9675837ef535b3308d6e31c208d43ebc44a0f7ab8a208c68f7"}, + {file = "jiter-0.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b1e7923093a376d93c6eb507c77045ae258d689ba577392846a1b3f10d0b09a9"}, + {file = "jiter-0.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2a0d46ef67cc58d906a6132dd3040ca70ae4f0b0d7c9c052fe432c658a69b3f6"}, + {file = "jiter-0.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:70a490b55634dc0d2606ce8a8e01b1d62459011beb368d15d76e1eaf62460e3d"}, + {file = "jiter-0.16.0-cp39-cp39-win32.whl", hash = "sha256:9acf1b2faec82d998811ecce7ae84d9005e53410773e9d37d61cdc424ba4581b"}, + {file = "jiter-0.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:491e7d072a253b156fff46b78bceac4652a697aa8d7082c9c18c03d7b7917d24"}, + {file = "jiter-0.16.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:850ccb1d7eedb4200f4014b1c0e8a577de114fc3cd88faad646dcc9bc4bb12ad"}, + {file = "jiter-0.16.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:e34e97bda77eb63242a410243c071e28ac7e0d8c0948c5ee658498690a4b2f2f"}, + {file = "jiter-0.16.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7dc85ea77d4abbae8bad0d3538678aedee75bceec4e2f6c8dfb1c74772e5aa5"}, + {file = "jiter-0.16.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17ca7fae79f6d99cd9a042b75f917eaada7b895cfc7dd2ee3a16089dcaec7a85"}, + {file = "jiter-0.16.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:f17d61a28b4b3e0e3e2ba98490c70501403b4d196f78732439160e7fd3678127"}, + {file = "jiter-0.16.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:96e38eea538c8ddf853a35727c7be0741c76c13f04148ac5c116222f50ece3b3"}, + {file = "jiter-0.16.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d284fb8d94d5855d60c44fefcab4bf966f1da6fada73992b01f6f0c9bc0c6702"}, + {file = "jiter-0.16.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d613743df53199b1aa256a7d328340da6d7078aac7705a7db9d7a791e9cfd2"}, + {file = "jiter-0.16.0.tar.gz", hash = "sha256:7b24c3492c5f4f84a37946ad9cf504910cf6a782d6a4e0689b6673c5894b4a1c"}, ] [[package]] @@ -3124,116 +2986,127 @@ rapidfuzz = ">=3.9.0,<4.0.0" [[package]] name = "librt" -version = "0.11.0" +version = "0.13.0" description = "Mypyc runtime library" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "platform_python_implementation != \"PyPy\"" files = [ - {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"}, - {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"}, - {file = "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"}, - {file = "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"}, - {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"}, - {file = "librt-0.11.0-cp310-cp310-win32.whl", hash = "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"}, - {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"}, - {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"}, - {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"}, - {file = "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"}, - {file = "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"}, - {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"}, - {file = "librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"}, - {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"}, - {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"}, - {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"}, - {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"}, - {file = "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"}, - {file = "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"}, - {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"}, - {file = "librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"}, - {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"}, - {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"}, - {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"}, - {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"}, - {file = "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"}, - {file = "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"}, - {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"}, - {file = "librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"}, - {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"}, - {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"}, - {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"}, - {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"}, - {file = "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"}, - {file = "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"}, - {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"}, - {file = "librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"}, - {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"}, - {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"}, - {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"}, - {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"}, - {file = "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"}, - {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"}, - {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"}, - {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"}, - {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"}, - {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"}, - {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"}, - {file = "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"}, - {file = "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"}, - {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"}, - {file = "librt-0.11.0-cp39-cp39-win32.whl", hash = "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"}, - {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"}, - {file = "librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"}, + {file = "librt-0.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:34e47058fcc69a313293d6dee94216a4f30c929ae6f2476e58c5ba635aa639d5"}, + {file = "librt-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dbdd5b6509d0c2a8fe72cf494c299a61dbd58142a90a4190664ae159e4a7b547"}, + {file = "librt-0.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e56ea4ee4df77585a6b5c138f6538680886024fa559f5b55bd14b12e98e67b2"}, + {file = "librt-0.13.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f1f9cc4d09a46d9cb3c2063ae100629d3f52a6517c3c08c2f4c9828261883929"}, + {file = "librt-0.13.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f125f5d46b20f89dc5587a55cc416b4ba2a5b2ffda36d048ee120e17598a653a"}, + {file = "librt-0.13.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2608d3b39f9e0b4a66a130d9150c615cba40a5090d25eeeaa225e0e46de8c0ac"}, + {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9fd35e95ab5e45c3901d37110263c7db85a961110f5460588fe37f8c131f88a7"}, + {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5f31b0aa13c9b04370d4da6be1ab7779776b3a075cceb6747a39a4be85fe1e40"}, + {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0b795f5fc70fbbb787ceaf79bb3a0d627bcc33c53de51741755263ec406b775a"}, + {file = "librt-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36b306a623aaad96fe4b378692b54f9c0789fccd833b9851753d5fbf6138cfde"}, + {file = "librt-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a3762e75fcac8c9e4dacaaf438bffd9003e2ca2c531b756f3c0035deefa674c8"}, + {file = "librt-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:d63bae12a8aeb51380be3438e4dc4bd27354d0f8e19166b2f44e3e94d6f552dc"}, + {file = "librt-0.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1b5a7bbff495baedbd9b916c367d66854008f8f3b575908ded477c499dc60082"}, + {file = "librt-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34bc7938b9fdf14fe32a406c19c71faf894c5cee7e7474bd0be2f17200b82d14"}, + {file = "librt-0.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f40e56b61b41be5f7dec938cfeffd660668cf4b5e72c78e7bd671d66b7bc2c79"}, + {file = "librt-0.13.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:9c5d02b89de5acd0379a51ec44a89476fb03df6145442e1c8ecd6bee2f91b176"}, + {file = "librt-0.13.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7db9a3ff32ef5f7d1703d93831a3316cdf0b537de6a1cc03cc8fdd09b9194e89"}, + {file = "librt-0.13.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3dbb2a31882456cadc7053378e81ad7ed7693db4ac9f98ab5f81ef034aa8ec9f"}, + {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c6014e3c80f9c1fe268ef8b0e0ef113bac672cc032f2f93866e7ddad4f3e663d"}, + {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:091b60a4d2174fc1ec5c34cdc0b72efb6224753d76b7da61ebeab7a191aec8bd"}, + {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:66cb1138f384a191a6d75f986064841fcfdc0cea98f7bd9c9ab9b38049917588"}, + {file = "librt-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:17221a7569f8f292aa0014226e48aa25b8c2b08da18088cd230953d0ea0f9cd1"}, + {file = "librt-0.13.0-cp311-cp311-win32.whl", hash = "sha256:fc67741da44c6eaa90e01eafb586bbba9b51eb5b6ed381ee6f5ae72eb3316d21"}, + {file = "librt-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:cc99dfb62b23c9207c33d0be8a2e2af7a42e21e6ea388b380a0c948c7b88953b"}, + {file = "librt-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:40ccd13c252d3fe473ffc8a57be7565abc8b64cf1b108344c859d5164f7f3e0c"}, + {file = "librt-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30536798f4504c0fad0885b1d371b0539abb081e4570c9d7c641cb51141b49f0"}, + {file = "librt-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93d24ebb82aa4420b1409c389e7857bc35bd0b668007ac8172427d5c73cc8cc5"}, + {file = "librt-0.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb8a1adce42d8b75485a5d56a9623a50bcab995b6079f1dac59fc44034dd93d9"}, + {file = "librt-0.13.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0763ca2ab66058174f9dee426dc64f5e0a89c24a7df8d3fe3f1836c04e25de4b"}, + {file = "librt-0.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b222493da6e7b6199db9bd79502436cf5a27da3c1f7fa83c7e285444fc93fd03"}, + {file = "librt-0.13.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fadc63331f4388c3dc90090448f682a7e9feafc11481391c1e94f2f907a3976e"}, + {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:70d9c62a4cffd9f23396cd5ef93fc5d11b31596b9b7d6306074abe3d5fcf09bd"}, + {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66c0e7e6b02a155576df2c77ec933a70b72da726e248c494abf690923e624348"}, + {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ac04bcd3328eb91d99dfedf6a60d9c1f15d3434e6f6daf922f0420f7d90b85c7"}, + {file = "librt-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db327e7271e653c32040b85ae6188059c924b57d7e1e29f935523fa017cd4e82"}, + {file = "librt-0.13.0-cp312-cp312-win32.whl", hash = "sha256:860bd1d8ba48456ce08feaf8d343a8aaeb2fa086f2bcaa2a923fa3f7a3ff9aa3"}, + {file = "librt-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:e54a315caf843c8d77e388cadc56ea9ded569935ee2d2347d7ea94992e5aa6fa"}, + {file = "librt-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:c718e99a0992127af84385378460db624103b559ab260435abcfe77a4e4ed1c1"}, + {file = "librt-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a468951af16155824e88bdd8326ebe5bdb371f3ec0ac04642994b98201d914f3"}, + {file = "librt-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae01d8512cc17079e53425635327dbf3f7ff57a42c00dec348bf79791c56444c"}, + {file = "librt-0.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32c26893cd085c1efe83219e78d866da23fb20a066101b8f68210004361d224c"}, + {file = "librt-0.13.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5929da1981a46bcf4b28b1b9499905f0ff58e2419da402a048234e9783acbc4b"}, + {file = "librt-0.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b85d664d777bab6c0d709416cb42938251fda9e221b79e3a2215d85df5f4f9"}, + {file = "librt-0.13.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:531b2df3e9fe96b1fcf73a6d165921e4656be5f58d631d384ebce344298368db"}, + {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:109b84a9edf69ad89dc1f66358659e14a031baca95e3e5b0060bd903ede8efd6"}, + {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1304368a3e7ffc3e9db986796cc5326fdb5943a3567ecc137cff318e4240c0e7"}, + {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e4f9b472e7d308d94b62c801982065661158c6ed02790d6c7ddb4337cea0f9c1"}, + {file = "librt-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f836c37478f167a81200d8c8b2c920a22224564bed2c23d7aeec760965c367a"}, + {file = "librt-0.13.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:4000d961ff9598ac6ea603c6c836a5ed49bc205ade5fc378b998dfe1e2c36628"}, + {file = "librt-0.13.0-cp313-cp313-win32.whl", hash = "sha256:79e44cff71750d299d61a678e49995b0d5935a9cda238c2574daeca3ba536927"}, + {file = "librt-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:54dab44a847d5ad1acd05c8a83fe518ae685516ecf4d3f7cc6e3df2a66767650"}, + {file = "librt-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:d4cb6fbfdf874340ab5e51450753c0f817b6958a3621125ee695bbc3de866566"}, + {file = "librt-0.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:25218d94b1d2cbc0ba1d8a3f9dc9af578d9646e5ed16443a70cde1dfdcce6d71"}, + {file = "librt-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f26629539d4893c2957a16c41bb058e1e135c1f150f6a2e25ed047f64cf3f5c6"}, + {file = "librt-0.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4517d47b2b8af26975a406fba7d314de9696d864252e0257c6ea90238cfe27f"}, + {file = "librt-0.13.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f19e181de5b3a1148bb3420b8c4b0b0ea0fce6950099724ad151d6cea5acc180"}, + {file = "librt-0.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22034924f5b42d5a56371cf271771bfeaabf235a7a8b6264bef2d20013f786c6"}, + {file = "librt-0.13.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7897db4e95e22468bdda33d8e012ceacd0182abf001e6389d763f0def6286b9"}, + {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ce61b3746545029d4f5c17d6bd74b676254ad98433086c846ffb5e8fa73f007"}, + {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:46c330e82565962c761dbce7941be2cff7db674ee807455a8d0cadc5f9b759b0"}, + {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:375f5af8f99cbaa99dd293af986e3d57caabc9ba81a5d3f021603764854197a1"}, + {file = "librt-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9320d34c3376ae204b2cd176e8d4883a013934e0aef822f1aed9c536490c275d"}, + {file = "librt-0.13.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9af313c66157a69dc69ea0059a66961692250e0dc95af9c385a48ffb770a0d16"}, + {file = "librt-0.13.0-cp314-cp314-win32.whl", hash = "sha256:f2a7253458e34f33543551394ae4fe104b497ec2a65ac266074de64c1df82e37"}, + {file = "librt-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:a3dfe4edf10e8ed7e55b026a8bfc2c2a8704218b659cd4bffdf604fab966dc39"}, + {file = "librt-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:68a5faee4bba381cb93b5961f684a514cf0053cb92308ff9c792c2fea0b174c6"}, + {file = "librt-0.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a38fb81d8376dfa2f8963b265fec07637802b0d01e2a127c19c66cb070fb24f5"}, + {file = "librt-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d4c8d9bd5abce34b2e75edb3bf37ab0f34e49b1f915a40ae8468eb7c85bc5b46"}, + {file = "librt-0.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:387e2f1d27e89bffe0d3f520f0da0662c973fd607ca16c1808f8a5085419485e"}, + {file = "librt-0.13.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:4f6db193d2e5e0ed60359b9a5a682cd67205d0d3b1e459a867dd4b5c4e7eaa7a"}, + {file = "librt-0.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d38604854e8d22faadf683ec6c02bb0f886e2ba56ef981a1c36ee275f21ea22"}, + {file = "librt-0.13.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:371f7ce73026815dafd51c50ce38416e91428b28c4b2ec97cd39271164b0045c"}, + {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3aaedf52171bee90860704c560bc798fe83b76247df47568e0197e9b13c735a0"}, + {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:96bad8725a4f196a798366c25ce075d1f7543a4ec045ffc13e6a7ec095cdab04"}, + {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6bf6a559ffe4a93bbea6cf31ddf01a7fd9ba342ef51f27beb178e318b74acd61"}, + {file = "librt-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:301067672387902c55f94b51d5022304b36c966ea9fe1f21caab99a9bef487c9"}, + {file = "librt-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:5fdcf34f86de8fb66d7dc7589f96ba91c4aa46671200d400e6fd6f109a483f18"}, + {file = "librt-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:260c33e92263fa629b4f6d3c51967a1c2158fe6c33237aaa3ebeac586b085259"}, + {file = "librt-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2f281549a4c52ac7bb97997f14353f8bd0e53a34ca0dad1c905cfd0b4a58ae99"}, + {file = "librt-0.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f442e3954b1addc759faae22a7c9a3f1e16d7d1db3f484279dc27d62e06968fa"}, + {file = "librt-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e786428f291dd2d2f1cbfc0e0caa45a2e395fab0ad3e2c9314daa8873414390"}, + {file = "librt-0.13.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21b7ac084f701a9cdff6139745a6620579d65a9379ac2d9d50a86368b109e63c"}, + {file = "librt-0.13.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a6e556d6aba31c93dd97ce661d66614d2429c0a3923f9dc8f0af7e8df10223a4"}, + {file = "librt-0.13.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3657346f867469e962549435aa05fd15330b1d6a92829f8e27988e194382d005"}, + {file = "librt-0.13.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:791aa18a373b90da8ac3c44fc77544f33fdf53ae403acdce9b39f1c26b4a3b94"}, + {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d6fb0eaa108814581c4d3bfbd068c3fb6757812a81415008d1bae08267cca360"}, + {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a001519c315d5db40710f2665d32c4791f1d4779fc96a9423fd18d92c8b9ac7b"}, + {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:d9188caac26e47671b52836a5e2a49873a7fc11c673b0c122d22515f98bc14e1"}, + {file = "librt-0.13.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:05d96b80b95d3a2721b619f8982b8558848b04875bb4772fd54842b59f61dd97"}, + {file = "librt-0.13.0-cp39-cp39-win32.whl", hash = "sha256:c3cd253cf32fe4f4662960d6bf7d55cb8be0c31a5d644a4d48aeafebaff3409a"}, + {file = "librt-0.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:b15e26cc0fe622d0c67e98bee6ef6bc8f792e20ee3006aa12627a00463d9399f"}, + {file = "librt-0.13.0.tar.gz", hash = "sha256:1d2a610c14ac0d0750ee0a3ab8548e83155258387891caaca04def4bf7289781"}, ] [[package]] name = "litellm" -version = "1.88.1" +version = "1.93.0" description = "Library to easily interface with LLM API providers" optional = false -python-versions = "<3.14,>=3.10" +python-versions = "<3.15,>=3.10" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "litellm-1.88.1-py3-none-any.whl", hash = "sha256:369b84e57d9426582ddc35e731956ddb6618cda97cc44e4e4d2dfa75982a6e3a"}, - {file = "litellm-1.88.1.tar.gz", hash = "sha256:89c6b74cc7912d6365793006ff951c0450fe847625008dfe49de8a7dc4529aa5"}, + {file = "litellm-1.93.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:5d84aead083d3d0619b2d293f8006ebbe75611bbdcef470d659c9e2d131d4454"}, + {file = "litellm-1.93.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6b49f653e6205cbc725257da8797277f77065c69865fb3489bc5ed0896b66ee0"}, + {file = "litellm-1.93.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:952029d422c2cec8117b444d66d6de87ac970ecf0b2e1383b02788ef90ba3603"}, + {file = "litellm-1.93.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:460001b7c88c5b6675ad482ae3cecba96e21f890604b4febb1a67807ace1c750"}, + {file = "litellm-1.93.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3daf5c5aceb07f5d68871071e0ecdc678caccebadca9143cc00bb76f5a8c54e8"}, + {file = "litellm-1.93.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:0784172435de48f66ef7ad89d421604db1ad0db1321ef7f39dbcfe6b20111417"}, + {file = "litellm-1.93.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:23b8eea4fb8b3b6ade05e7b6085ec9ca12daffcfb38d033d0bbce9c1d5894da5"}, + {file = "litellm-1.93.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:98c15e84d32e922a821c105308bf9ddae8700de9ed396530bee2cbb1cacf4cbb"}, + {file = "litellm-1.93.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:1a476ebc340c070c982eab15b4673fa63a70f5936935f9f20e4d2acb5f35d23b"}, + {file = "litellm-1.93.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:cd70ccd4ba3ef1a395535c287bce72d30c7d937ecca4290c0db37a00738f7ada"}, + {file = "litellm-1.93.0.tar.gz", hash = "sha256:140bf215e264c71601bca9c06d2436c5451bb59e1e195ea23fc2d3d87b6929ec"}, ] [package.dependencies] @@ -3252,158 +3125,159 @@ tokenizers = ">=0.21.0,<1.0" [package.extras] caching = ["diskcache (>=5.6.3,<6.0)"] -extra-proxy = ["a2a-sdk (>=0.3.24,<1.0)", "azure-identity (>=1.25.2,<2.0)", "azure-keyvault-secrets (>=4.10.0,<5.0)", "google-cloud-iam (>=2.19.1,<3.0)", "google-cloud-kms (>=2.24.2,<3.0)", "prisma (>=0.11.0,<1.0)", "redisvl (>=0.4.1,<1.0) ; python_full_version < \"3.14.0\"", "resend (>=2.23.0,<3.0)"] +cli = ["pyyaml (>=6.0.3,<7.0)", "requests (>=2.32.0,<3.0)", "rich (>=13.9.4,<14.0)"] +extra-proxy = ["a2a-sdk (>=1.1.0,<2.0)", "azure-identity (>=1.25.2,<2.0)", "azure-keyvault-secrets (>=4.10.0,<5.0)", "google-cloud-iam (>=2.19.1,<3.0)", "google-cloud-kms (>=2.24.2,<3.0)", "prisma (>=0.11.0,<1.0)", "redisvl (>=0.4.1,<1.0)", "resend (>=2.23.0,<3.0)"] google = ["google-cloud-aiplatform (>=1.133.0,<2.0)"] grpc = ["grpcio (==1.78.0)"] mlflow = ["mlflow (>=3.11.1,<4.0)"] -proxy = ["apscheduler (>=3.11.2,<4.0)", "azure-identity (>=1.25.2,<2.0)", "azure-storage-blob (>=12.28.0,<13.0)", "backoff (>=2.2.1,<3.0)", "boto3 (>=1.43.1,<2.0)", "cryptography (>=46.0.7,<47.0)", "fastapi (>=0.136.3,<1.0)", "fastapi-sso (>=0.19.0,<1.0)", "granian (>=2.7.4,<3.0)", "gunicorn (>=23.0.0,<24.0)", "litellm-enterprise (==0.1.42)", "litellm-proxy-extras (==0.4.73)", "mcp (>=1.26.0,<2.0)", "orjson (>=3.11.6,<4.0)", "polars (>=1.38.1,<2.0)", "pydantic-settings (>=2.14.1,<3.0)", "pyjwt (>=2.13.0,<3.0)", "pynacl (>=1.6.2,<2.0)", "pyroscope-io (>=0.8.16,<1.0) ; sys_platform != \"win32\"", "python-multipart (>=0.0.27,<1.0)", "pyyaml (>=6.0.3,<7.0)", "restrictedpython (>=8.1,<9.0)", "rich (>=13.9.4,<14.0)", "rq (>=2.7.0,<3.0)", "soundfile (>=0.12.1,<1.0)", "starlette (>=1.0.1,<2.0)", "uvicorn (>=0.33.0,<1.0)", "uvloop (>=0.21.0,<1.0) ; sys_platform != \"win32\"", "websockets (>=15.0.1,<16.0)"] -proxy-runtime = ["anthropic[vertex] (>=0.84.0,<1.0)", "azure-ai-contentsafety (>=1.0.0,<2.0)", "azure-storage-file-datalake (>=12.20.0,<13.0)", "ddtrace (>=2.19.0,<3.0)", "detect-secrets (>=1.5.0,<2.0)", "google-cloud-aiplatform (>=1.133.0,<2.0)", "google-genai (>=1.37.0,<2.0)", "grpcio (==1.78.0)", "langfuse (>=2.59.7,<3.0)", "llm-sandbox (>=0.3.39,<1.0)", "mangum (>=0.17.0,<1.0)", "opentelemetry-api (==1.28.0)", "opentelemetry-exporter-otlp (==1.28.0)", "opentelemetry-instrumentation-fastapi (==0.49b0)", "opentelemetry-sdk (==1.28.0)", "prometheus-client (>=0.20.0,<1.0)", "pypdf (>=6.10.2,<7.0) ; python_full_version < \"3.14.0\"", "sentry-sdk (>=2.21.0,<3.0)"] +proxy = ["apscheduler (>=3.11.2,<4.0)", "azure-identity (>=1.25.2,<2.0)", "azure-storage-blob (>=12.28.0,<13.0)", "backoff (>=2.2.1,<3.0)", "boto3 (>=1.43.1,<2.0)", "cryptography (>=48.0.1,<49.0)", "expression (>=5.6.0,<6.0)", "fastapi (>=0.136.3,<1.0)", "fastapi-sso (>=0.19.0,<1.0)", "granian (>=2.7.4,<3.0)", "gunicorn (>=23.0.0,<24.0)", "litellm-enterprise (==0.1.49)", "litellm-proxy-extras (==0.4.76)", "mcp (>=1.28.1,<2.0)", "orjson (>=3.11.6,<4.0)", "polars (>=1.38.1,<2.0)", "pydantic-settings (>=2.14.1,<3.0)", "pyjwt (>=2.13.0,<3.0)", "pynacl (>=1.6.2,<2.0)", "pyroscope-io (>=0.8.16,<1.0) ; sys_platform != \"win32\"", "python-multipart (>=0.0.27,<1.0)", "pyyaml (>=6.0.3,<7.0)", "restrictedpython (>=8.1,<9.0)", "rich (>=13.9.4,<14.0)", "rq (>=2.7.0,<3.0)", "soundfile (>=0.12.1,<1.0)", "starlette (>=1.0.1,<2.0)", "uvicorn (>=0.33.0,<1.0)", "uvloop (>=0.21.0,<1.0) ; sys_platform != \"win32\"", "websockets (>=15.0.1,<16.0)"] +proxy-runtime = ["anthropic[vertex] (>=0.84.0,<1.0)", "azure-ai-contentsafety (>=1.0.0,<2.0)", "azure-storage-file-datalake (>=12.20.0,<13.0)", "ddtrace (>=4.8.2,<5.0)", "detect-secrets (>=1.5.0,<2.0)", "google-cloud-aiplatform (>=1.133.0,<2.0)", "google-genai (>=1.37.0,<2.0)", "grpcio (==1.78.0)", "langfuse (>=2.59.7,<3.0)", "llm-sandbox (>=0.3.39,<1.0)", "mangum (>=0.17.0,<1.0)", "opentelemetry-api (==1.28.0)", "opentelemetry-exporter-otlp (==1.28.0)", "opentelemetry-instrumentation-fastapi (==0.49b0)", "opentelemetry-sdk (==1.28.0)", "prometheus-client (>=0.20.0,<1.0)", "pypdf (>=6.12.0,<7.0)", "sentry-sdk (>=2.21.0,<3.0)"] semantic-router = ["aurelio-sdk (>=0.0.19,<1.0) ; python_full_version < \"3.14.0\"", "semantic-router (>=0.1.15,<1.0) ; python_full_version < \"3.14.0\""] stt-nvidia-riva = ["audioread (>=3.0.1)", "numpy (>=1.26.0)", "nvidia-riva-client (>=2.15.0)", "soundfile (>=0.12.1)"] utils = ["numpydoc (>=1.8.0,<2.0)"] [[package]] name = "lxml" -version = "6.1.0" +version = "6.1.1" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "lxml-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:41dcc4c7b10484257cbd6c37b83ddb26df2b0e5aff5ac00d095689015af868ec"}, - {file = "lxml-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a31286dbb5e74c8e9a5344465b77ab4c5bd511a253b355b5ca2fae7e579fafec"}, - {file = "lxml-6.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1bc4cc83fb7f66ffb16f74d6dd0162e144333fc36ebcce32246f80c8735b2551"}, - {file = "lxml-6.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:20cf4d0651987c906a2f5cba4e3a8d6ba4bfdf973cfe2a96c0d6053888ea2ecd"}, - {file = "lxml-6.1.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffb34ea45a82dd637c2c97ae1bbb920850c1e59bcae79ce1c15af531d83e7215"}, - {file = "lxml-6.1.0-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1d9b99e5b2597e4f5aed2484fef835256fa1b68a19e4265c97628ef4bf8bcf4"}, - {file = "lxml-6.1.0-cp310-cp310-manylinux_2_28_i686.whl", hash = "sha256:d43aa26dcda363f21e79afa0668f5029ed7394b3bb8c92a6927a3d34e8b610ea"}, - {file = "lxml-6.1.0-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:6262b87f9e5c1e5fe501d6c153247289af42eb44ad7660b9b3de17baaf92d6f6"}, - {file = "lxml-6.1.0-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d1392c569c032f78a11a25d1de1c43fff13294c793b39e19d84fade3045cbbc3"}, - {file = "lxml-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:045e387d1f4f42a418380930fa3f45c73c9b392faf67e495e58902e68e8f44a7"}, - {file = "lxml-6.1.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:9f93d5b8b07f73e8c77e3c6556a3db269918390c804b5e5fcdd4858232cc8f16"}, - {file = "lxml-6.1.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:de550d129f18d8ab819651ffe4f38b1b713c7e116707de3c0c6400d0ef34fbc1"}, - {file = "lxml-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c08da09dc003c9e8c70e06b53a11db6fb3b250c21c4236b03c7d7b443c318e7a"}, - {file = "lxml-6.1.0-cp310-cp310-win32.whl", hash = "sha256:37448bf9c7d7adfc5254763901e2bbd6bb876228dfc1fc7f66e58c06368a7544"}, - {file = "lxml-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:2593a0a6621545b9095b71ad74ed4226eba438a7d9fc3712a99bdb15508cf93a"}, - {file = "lxml-6.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:e80807d72f96b96ad5588cb85c75616e4f2795a7737d4630784c51497beb7776"}, - {file = "lxml-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cec05be8c876f92a5aa07b01d60bbb4d11cfbdd654cad0561c0d7b5c043a61b9"}, - {file = "lxml-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9c03e048b6ce8e77b09c734e931584894ecd58d08296804ca2d0b184c933ce50"}, - {file = "lxml-6.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:942454ff253da14218f972b23dc72fa4edf6c943f37edd19cd697618b626fac5"}, - {file = "lxml-6.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d036ee7b99d5148072ac7c9b847193decdfeac633db350363f7bce4fff108f0e"}, - {file = "lxml-6.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ae5d8d5427f3cc317e7950f2da7ad276df0cfa37b8de2f5658959e618ea8512"}, - {file = "lxml-6.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:363e47283bde87051b821826e71dde47f107e08614e1aa312ba0c5711e77738c"}, - {file = "lxml-6.1.0-cp311-cp311-manylinux_2_28_i686.whl", hash = "sha256:f504d861d9f2a8f94020130adac88d66de93841707a23a86244263d1e54682f5"}, - {file = "lxml-6.1.0-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:23a5dc68e08ed13331d61815c08f260f46b4a60fdd1640bbeb82cf89a9d90289"}, - {file = "lxml-6.1.0-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f15401d8d3dbf239e23c818afc10c7207f7b95f9a307e092122b6f86dd43209a"}, - {file = "lxml-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fcf3da95e93349e0647d48d4b36a12783105bcc74cb0c416952f9988410846a3"}, - {file = "lxml-6.1.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:0d082495c5fcf426e425a6e28daaba1fcb6d8f854a4ff01effb1f1f381203eb9"}, - {file = "lxml-6.1.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e3c4f84b24a1fcba435157d111c4b755099c6ff00a3daee1ad281817de75ed11"}, - {file = "lxml-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:976a6b39b1b13e8c354ad8d3f261f3a4ac6609518af91bdb5094760a08f132c4"}, - {file = "lxml-6.1.0-cp311-cp311-win32.whl", hash = "sha256:857efde87d365706590847b916baff69c0bc9252dc5af030e378c9800c0b10e3"}, - {file = "lxml-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:183bfb45a493081943be7ea2b5adfc2b611e1cf377cefa8b8a8be404f45ef9a7"}, - {file = "lxml-6.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:19f4164243fc206d12ed3d866e80e74f5bc3627966520da1a5f97e42c32a3f39"}, - {file = "lxml-6.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d2f17a16cd8751e8eb233a7e41aecdf8e511712e00088bf9be455f604cd0d28d"}, - {file = "lxml-6.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f0cea5b1d3e6e77d71bd2b9972eb2446221a69dc52bb0b9c3c6f6e5700592d93"}, - {file = "lxml-6.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fc46da94826188ed45cb53bd8e3fc076ae22675aea2087843d4735627f867c6d"}, - {file = "lxml-6.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9147d8e386ec3b82c3b15d88927f734f565b0aaadef7def562b853adca45784a"}, - {file = "lxml-6.1.0-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5715e0e28736a070f3f34a7ccc09e2fdcba0e3060abbcf61a1a5718ff6d6b105"}, - {file = "lxml-6.1.0-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4937460dc5df0cdd2f06a86c285c28afda06aefa3af949f9477d3e8df430c485"}, - {file = "lxml-6.1.0-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bc783ee3147e60a25aa0445ea82b3e8aabb83b240f2b95d32cb75587ff781814"}, - {file = "lxml-6.1.0-cp312-cp312-manylinux_2_28_i686.whl", hash = "sha256:40d9189f80075f2e1f88db21ef815a2b17b28adf8e50aaf5c789bfe737027f32"}, - {file = "lxml-6.1.0-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:05b9b8787e35bec69e68daf4952b2e6dfcfb0db7ecf1a06f8cdfbbac4eb71aad"}, - {file = "lxml-6.1.0-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0f0f08beb0182e3e9a86fae124b3c47a7b41b7b69b225e1377db983802404e54"}, - {file = "lxml-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73becf6d8c81d4c76b1014dbd3584cb26d904492dcf73ca85dc8bff08dcd6d2d"}, - {file = "lxml-6.1.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1ae225f66e5938f4fa29d37e009a3bb3b13032ac57eb4eb42afa44f6e4054e69"}, - {file = "lxml-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:690022c7fae793b0489aa68a658822cea83e0d5933781811cabbf5ea3bcfe73d"}, - {file = "lxml-6.1.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:63aeafc26aac0be8aff14af7871249e87ea1319be92090bfd632ec68e03b16a5"}, - {file = "lxml-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:264c605ab9c0e4aa1a679636f4582c4d3313700009fac3ec9c3412ed0d8f3e1d"}, - {file = "lxml-6.1.0-cp312-cp312-win32.whl", hash = "sha256:56971379bc5ee8037c5a0f09fa88f66cdb7d37c3e38af3e45cf539f41131ac1f"}, - {file = "lxml-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bba078de0031c219e5dd06cf3e6bf8fb8e6e64a77819b358f53bb132e3e03366"}, - {file = "lxml-6.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:c3592631e652afa34999a088f98ba7dfc7d6aff0d535c410bea77a71743f3819"}, - {file = "lxml-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a0092f2b107b69601adf562a57c956fbb596e05e3e6651cabd3054113b007e45"}, - {file = "lxml-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fc7140d7a7386e6b545d41b7358f4d02b656d4053f5fa6859f92f4b9c2572c4d"}, - {file = "lxml-6.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:419c58fc92cc3a2c3fa5f78c63dbf5da70c1fa9c1b25f25727ecee89a96c7de2"}, - {file = "lxml-6.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:37fabd1452852636cf38ecdcc9dd5ca4bba7a35d6c53fa09725deeb894a87491"}, - {file = "lxml-6.1.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2853c8b2170cc6cd54a6b4d50d2c1a8a7aeca201f23804b4898525c7a152cfc"}, - {file = "lxml-6.1.0-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8e369cbd690e788c8d15e56222d91a09c6a417f49cbc543040cba0fe2e25a79e"}, - {file = "lxml-6.1.0-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e69aa6805905807186eb00e66c6d97a935c928275182eb02ee40ba00da9623b2"}, - {file = "lxml-6.1.0-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:4bd1bdb8a9e0e2dd229de19b5f8aebac80e916921b4b2c6ef8a52bc131d0c1f9"}, - {file = "lxml-6.1.0-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:cbd7b79cdcb4986ad78a2662625882747f09db5e4cd7b2ae178a88c9c51b3dfe"}, - {file = "lxml-6.1.0-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:43e4d297f11080ec9d64a4b1ad7ac02b4484c9f0e2179d9c4ef78e886e747b88"}, - {file = "lxml-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cc16682cc987a3da00aa56a3aa3075b08edb10d9b1e476938cfdbee8f3b67181"}, - {file = "lxml-6.1.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d6d8efe71429635f0559579092bb5e60560d7b9115ee38c4adbea35632e7fa24"}, - {file = "lxml-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7e39ab3a28af7784e206d8606ec0e4bcad0190f63a492bca95e94e5a4aef7f6e"}, - {file = "lxml-6.1.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:9eb667bf50856c4a58145f8ca2d5e5be160191e79eb9e30855a476191b3c3495"}, - {file = "lxml-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7f4a77d6f7edf9230cee3e1f7f6764722a41604ee5681844f18db9a81ea0ec33"}, - {file = "lxml-6.1.0-cp313-cp313-win32.whl", hash = "sha256:28902146ffbe5222df411c5d19e5352490122e14447e98cd118907ee3fd6ee62"}, - {file = "lxml-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:4a1503c56e4e2b38dc76f2f2da7bae69670c0f1933e27cfa34b2fa5876410b16"}, - {file = "lxml-6.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:e0af85773850417d994d019741239b901b22c6680206f46a34766926e466141d"}, - {file = "lxml-6.1.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:ab863fd37458fed6456525f297d21239d987800c46e67da5ef04fc6b3dd93ac8"}, - {file = "lxml-6.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6fd8b1df8254ff4fd93fd31da1fc15770bde23ac045be9bb1f87425702f61cc9"}, - {file = "lxml-6.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:47024feaae386a92a146af0d2aeed65229bf6fff738e6a11dda6b0015fb8fd03"}, - {file = "lxml-6.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3f00972f84450204cd5d93a5395965e348956aaceaadec693a22ec743f8ae3eb"}, - {file = "lxml-6.1.0-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97faa0860e13b05b15a51fb4986421ef7a30f0b3334061c416e0981e9450ca4c"}, - {file = "lxml-6.1.0-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:972a6451204798675407beaad97b868d0c733d9a74dafefc63120b81b8c2de28"}, - {file = "lxml-6.1.0-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fe022f20bc4569ec66b63b3fb275a3d628d9d32da6326b2982584104db6d3086"}, - {file = "lxml-6.1.0-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:75c4c7c619a744f972f4451bf5adf6d0fb00992a1ffc9fd78e13b0bc817cc99f"}, - {file = "lxml-6.1.0-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:3648f20d25102a22b6061c688beb3a805099ea4beb0a01ce62975d926944d292"}, - {file = "lxml-6.1.0-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:77b9f99b17cbf14026d1e618035077060fc7195dd940d025149f3e2e830fbfcb"}, - {file = "lxml-6.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32662519149fd7a9db354175aa5e417d83485a8039b8aaa62f873ceee7ea4cad"}, - {file = "lxml-6.1.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:73d658216fc173cf2c939e90e07b941c5e12736b0bf6a99e7af95459cfe8eabb"}, - {file = "lxml-6.1.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ac4db068889f8772a4a698c5980ec302771bb545e10c4b095d4c8be26749616f"}, - {file = "lxml-6.1.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:45e9dfbd1b661eb64ba0d4dbe762bd210c42d86dd1e5bd2bdf89d634231beb43"}, - {file = "lxml-6.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:89e8d73d09ac696a5ba42ec69787913d53284f12092f651506779314f10ba585"}, - {file = "lxml-6.1.0-cp314-cp314-win32.whl", hash = "sha256:ebe33f4ec1b2de38ceb225a1749a2965855bffeef435ba93cd2d5d540783bf2f"}, - {file = "lxml-6.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:398443df51c538bd578529aa7e5f7afc6c292644174b47961f3bf87fe5741120"}, - {file = "lxml-6.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:8c8984e1d8c4b3949e419158fda14d921ff703a9ed8a47236c6eb7a2b6cb4946"}, - {file = "lxml-6.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:1081dd10bc6fa437db2500e13993abf7cc30716d0a2f40e65abb935f02ec559c"}, - {file = "lxml-6.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:dabecc48db5f42ba348d1f5d5afdc54c6c4cc758e676926c7cd327045749517d"}, - {file = "lxml-6.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e3dd5fe19c9e0ac818a9c7f132a5e43c1339ec1cbbfecb1a938bd3a47875b7c9"}, - {file = "lxml-6.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9e7b0a4ca6dcc007a4cef00a761bba2dea959de4bd2df98f926b33c92ca5dfb9"}, - {file = "lxml-6.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d27bbe326c6b539c64b42638b18bc6003a8d88f76213a97ac9ed4f885efeab7"}, - {file = "lxml-6.1.0-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4e425db0c5445ef0ad56b0eec54f89b88b2d884656e536a90b2f52aecb4ca86"}, - {file = "lxml-6.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4b89b098105b8599dc57adac95d1813409ac476d3c948a498775d3d0c6124bfb"}, - {file = "lxml-6.1.0-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:c4a699432846df86cc3de502ee85f445ebad748a1c6021d445f3e514d2cd4b1c"}, - {file = "lxml-6.1.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:30e7b2ed63b6c8e97cca8af048589a788ab5c9c905f36d9cf1c2bb549f450d2f"}, - {file = "lxml-6.1.0-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:022981127642fe19866d2907d76241bb07ed21749601f727d5d5dd1ce5d1b773"}, - {file = "lxml-6.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:23cad0cc86046d4222f7f418910e46b89971c5a45d3c8abfad0f64b7b05e4a9b"}, - {file = "lxml-6.1.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:21c3302068f50d1e8728c67c87ba92aa87043abee517aa2576cca1855326b405"}, - {file = "lxml-6.1.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:be10838781cb3be19251e276910cd508fe127e27c3242e50521521a0f3781690"}, - {file = "lxml-6.1.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2173a7bffe97667bbf0767f8a99e587740a8c56fdf3befac4b09cb29a80276fd"}, - {file = "lxml-6.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c6854e9cf99c84beb004eecd7d3a3868ef1109bf2b1df92d7bc11e96a36c2180"}, - {file = "lxml-6.1.0-cp314-cp314t-win32.whl", hash = "sha256:00750d63ef0031a05331b9223463b1c7c02b9004cef2346a5b2877f0f9494dd2"}, - {file = "lxml-6.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:80410c3a7e3c617af04de17caa9f9f20adaa817093293d69eae7d7d0522836f5"}, - {file = "lxml-6.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:26dd9f57ee3bd41e7d35b4c98a2ffd89ed11591649f421f0ec19f67d50ec67ac"}, - {file = "lxml-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b6c2f225662bc5ad416bdd06f72ca301b31b39ce4261f0e0097017fc2891b940"}, - {file = "lxml-6.1.0-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a86f06f059e22a0d574990ee2df24ede03f7f3c68c1336293eee9536c4c776cd"}, - {file = "lxml-6.1.0-cp38-cp38-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:468479e52ecf3ec23799c863336d02c05fc2f7ffd1a1424eeeb9a28d4eb69d13"}, - {file = "lxml-6.1.0-cp38-cp38-manylinux_2_28_i686.whl", hash = "sha256:a02ca8fe48815bddcfca3248efe54451abb9dbf2f7d1c5744c8aa4142d476919"}, - {file = "lxml-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bb40648d96157f9081886defe13eac99253e663be969ff938a9289eff6e47b72"}, - {file = "lxml-6.1.0-cp38-cp38-win32.whl", hash = "sha256:1dd6a1c3ad4cb674f44525d9957f3e9c209bb6dd9213245195167a281fcc2bdc"}, - {file = "lxml-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:4e2c54d6b47361d0f1d3bc8d4e082ad87201e56ccdcca4d3b9ee3644ff595ec8"}, - {file = "lxml-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:920354904d1cb86577d4b3cfe2830c2dbe81d6f4449e57ada428f1609b5985f7"}, - {file = "lxml-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c871299c595ee004d186f61840f0bfc4941aa3f17c8ba4a565ead7e4f4f820ee"}, - {file = "lxml-6.1.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d0d799ff958655781296ec870d5e2448e75150da2b3d07f13ff5b0c2c35beefd"}, - {file = "lxml-6.1.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ba11752e346bd804ea312ec2eea2532dfa8b8d3261d81a32ef9e6ab16256280"}, - {file = "lxml-6.1.0-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:26c5272c6a4bf4cf32d3f5a7890c942b0e04438691157d341616d02cca74d4bd"}, - {file = "lxml-6.1.0-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c53fa3a5a52122d590e847a57ccf955557b9634a7f99ff5a35131321b0a85317"}, - {file = "lxml-6.1.0-cp39-cp39-manylinux_2_28_i686.whl", hash = "sha256:76b958b4ea3104483c20f74866d55aa056546e15ebe83dd7aecd63698f43b755"}, - {file = "lxml-6.1.0-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:8c11b984b5ce6add4dccc7144c7be5d364d298f15b0c6a57da1991baedc750ce"}, - {file = "lxml-6.1.0-cp39-cp39-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d3829a6e6fd550a219564912d4002c537f65da4c6ae4e093cc34462f4fa027ad"}, - {file = "lxml-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:52b0ac6903cf74ebf997eb8c682d2fbac7d1ab7e4c552413eec55868a9b73f39"}, - {file = "lxml-6.1.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:29f5c00cb7d752bce2c70ebd2d31b0a42f9499ffdd3ecb2f31a5b73ee43031ad"}, - {file = "lxml-6.1.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:c748ebcb6877de89f48ab90ca96642ac458fff5dec291a2b9337cd4d0934e383"}, - {file = "lxml-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:08950a23f296b3f83521577274e3d3b0f3d739bf2e68d01a752e4288bc50d286"}, - {file = "lxml-6.1.0-cp39-cp39-win32.whl", hash = "sha256:11a873c77a181b4fef9c2e357d08ed399542c2af1390101da66720a19c7c9618"}, - {file = "lxml-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:81ff55c70b67d19d52b6fd118a114c0a4c97d799cd3089ff9bd9e2ff4b414ee2"}, - {file = "lxml-6.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:481d6e2104285d9add34f41b42b247b76b61c5b5c26c303c2e9707bbf8bd9a64"}, - {file = "lxml-6.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:546b66c0dd1bb8d9fa89d7123e5fa19a8aff3a1f2141eb22df96112afb17b842"}, - {file = "lxml-6.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5cfa1a34df366d9dc0d5eaf420f4cf2bb1e1bebe1066d1c2fc28c179f8a4004c"}, - {file = "lxml-6.1.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db88156fcf544cdbf0d95588051515cfdfd4c876fc66444eb98bceb5d6db76de"}, - {file = "lxml-6.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:07f98f5496f96bf724b1e3c933c107f0cbf2745db18c03d2e13a291c3afd2635"}, - {file = "lxml-6.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4642e04449a1e164b5ff71ffd901ddb772dfabf5c9adf1b7be5dffe1212bc037"}, - {file = "lxml-6.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:7da13bb6fbadfafb474e0226a30570a3445cfd47c86296f2446dafbd77079ace"}, - {file = "lxml-6.1.0.tar.gz", hash = "sha256:bfd57d8008c4965709a919c3e9a98f76c2c7cb319086b3d26858250620023b13"}, + {file = "lxml-6.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:09dd5b7075dc2f7709654a46543ba1ea3c2e217b2ed8fbd413a8a945a0f40f60"}, + {file = "lxml-6.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f6ac4ef4d82dff54670227a69c67782ae0b811b5cf6b17954f1e8f7502fc0d1d"}, + {file = "lxml-6.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:556e94a63c9b04716f8e4de2abb65775061f846e89331b6c5be79183a24f98ea"}, + {file = "lxml-6.1.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5c6bf403fbb3b3e348a561a5f4f0b9961835657981c802a1df03653eef8a9074"}, + {file = "lxml-6.1.1-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1dde6131244bba38a17c745836ba190bc753fd73c9291666287fd0a3fa3dcf30"}, + {file = "lxml-6.1.1-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98fc784c2c1440667aeedf8465bdfe10208acf0ead656a2c68627299f546b315"}, + {file = "lxml-6.1.1-cp310-cp310-manylinux_2_28_i686.whl", hash = "sha256:add8cf6ddf9a65116119a28ece0f7886e30af27ba724a7594305f1d1b58a92a1"}, + {file = "lxml-6.1.1-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:cf9d57306d848218f3601fee7601fab1a327c942d56e2e97610583cb4dd74206"}, + {file = "lxml-6.1.1-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:88136950da4d13c318bde414ce10219931937851327f44328f2df4d2c4614067"}, + {file = "lxml-6.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cecdd5dfdc87b1fd87dbf81d4b037a544f47f4c744200a67013771682d67686a"}, + {file = "lxml-6.1.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:cd312b9692e831d2ffcad61eab31d91d4b4655a962e61de8fb410472cbcd37aa"}, + {file = "lxml-6.1.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:5b7328b46d49fc9477d91ae8f6d55340347d827b7734ba3ea33faae0efef1383"}, + {file = "lxml-6.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37a58976370f36d9329d118ad0b953c5aeb9119ac9c6a4e258942a225d0573a1"}, + {file = "lxml-6.1.1-cp310-cp310-win32.whl", hash = "sha256:cea3f4c1af79af13cdb2da0c028111d8f8522d4f22a000c82385535f24e5cf3a"}, + {file = "lxml-6.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:3abf332af33a74288675d936fe861fd4344da0dd6622193fbc4f2bfbb35536b5"}, + {file = "lxml-6.1.1-cp310-cp310-win_arm64.whl", hash = "sha256:8dadbe5b217ff35b6a8d16610dd710219b59b76d13f0e3f0d9f36786206e4485"}, + {file = "lxml-6.1.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:53b7d2b7a10b1c35c0a5e21e9224accf60c1bbfba523990732e521b2b73adef2"}, + {file = "lxml-6.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3f333630ab480244a1bff72043e511a91eb22e7595dead8653ee5612dd8f3d"}, + {file = "lxml-6.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a4bbea04c97f6d78a48e3fbc1cb9116d2780b1b39e03a23f6eb9b603fd61f510"}, + {file = "lxml-6.1.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:db1d75f6617a49c1c01bc7023713e0ff59ab32c9579ae62a7674c0e34f3b0b0a"}, + {file = "lxml-6.1.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a12689be69a28ddaa0ab99a5a1137da2afd5f8f16df7b5680b66f616d3eda1d"}, + {file = "lxml-6.1.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b73c339ae29b90fd2d06e58ebd555a751bde9cd6bbd36cc0281b9a2c94e9d8"}, + {file = "lxml-6.1.1-cp311-cp311-manylinux_2_28_i686.whl", hash = "sha256:752d3bbfe874715ccd0aec7f88d7fc623c0f1fd7aa7b3238a084e017bad2a009"}, + {file = "lxml-6.1.1-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:6b1761fbf9ec984e2e9d9c589ef5f5fd684b7c19f92aadd567a26c5224958db6"}, + {file = "lxml-6.1.1-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d680fbcb768404c601ecb43519ecd8461f6954cb11c06a78962f666832ccfca8"}, + {file = "lxml-6.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:162af1091cd785f2f27e62d3547ae9bc58ec5c86dd314d67021fd02463708d83"}, + {file = "lxml-6.1.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e9308ff8241c532df3f3e570f9a5aeed6c853f888512ba4b75638d7c11c95ef6"}, + {file = "lxml-6.1.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:5f6994074ebae6ffb04447268e37dc16edc304f9859cf91acb86e0af6c1b395c"}, + {file = "lxml-6.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:80c2dfadb855da477cf73373ad29a333535dedb9b12bad02c9814c8e2b43bf08"}, + {file = "lxml-6.1.1-cp311-cp311-win32.whl", hash = "sha256:30a89d3ac8faec007453fb541f3f46807eeec88edd5826f6e3fe001752a2c621"}, + {file = "lxml-6.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:abbefa31eee84842140f67acef1c828e28bba8bbf0c3bc6e5492a9af88152c28"}, + {file = "lxml-6.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:dcb292aa7fe485ceff7af4f92e46c5af397daec5dff64871a528f0fc47a3cc5b"}, + {file = "lxml-6.1.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:104c09bda8d2a562824c0e319d0768ce26a779b7601e0931d33b09b53c392ef7"}, + {file = "lxml-6.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:25c6997a9a534e016695a0ba06b2f07945de682731ff01065b6d5a4474179da1"}, + {file = "lxml-6.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c921ba5c51e4e9f63b8b00267d06566e1f63407408a0496da2d1d0bfc819c7fc"}, + {file = "lxml-6.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:54a7f95e4de5fb94e2f9f4b9055c6ba33bf3d628fd77a1d647c5923caa2cdcdc"}, + {file = "lxml-6.1.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f2ec43df44b1f76249ee0a615334f9b5b060e1c8bd90e706dad2d14d02f383"}, + {file = "lxml-6.1.1-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:70ef8a7e102a1508f8121aae5b0867abd663f72c14f0a9c937e6554cb4587b7b"}, + {file = "lxml-6.1.1-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ebe6af670449830d6d9b752c256a983291c766a1365ba5d5460048f9e33a7818"}, + {file = "lxml-6.1.1-cp312-cp312-manylinux_2_28_i686.whl", hash = "sha256:27acc820660aaffa4f7c087f29120e12980f7779d56d8492d263170111284740"}, + {file = "lxml-6.1.1-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:1db753c9115ec7100d073b744d17e25e88a8f90f5c39b2f5dd878149af59671f"}, + {file = "lxml-6.1.1-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4f469aebd783bb741c2ecb2a681008fd26bfe5c16a9a72ed5467f834e810df2"}, + {file = "lxml-6.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:766b010012d59470072c1816b5b6c69f1d243e5db36ea5968e94accf430a4635"}, + {file = "lxml-6.1.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b8d812c6011c08b8111a15e54dd990b8923692d80adf35488bee34026c35accf"}, + {file = "lxml-6.1.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:fe0306bd29505a9177aac19f1877174b0e7422c222a59f70b2cd41633448c3dc"}, + {file = "lxml-6.1.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5ba186ad207446c65d3bb3d3e0412b032b1d9f595e59861e2354798c5703d955"}, + {file = "lxml-6.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aa366a1e55b8ebfe8ca8ddc3cfe75c8ebade181aeb0f661d0cb05986b647f72a"}, + {file = "lxml-6.1.1-cp312-cp312-win32.whl", hash = "sha256:126c93f7f56f0eda92f6d8c619edc463a4f23d9252f1c9d0405a76f25fa9f11a"}, + {file = "lxml-6.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:26e6eda8d38c1fcab1090dd196ee87cbd13788e531937610e2589085de074e77"}, + {file = "lxml-6.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:6540377fbd53fe1b629172288c464fb18db11ce1fa7dc15891da10aa9dcc3e7f"}, + {file = "lxml-6.1.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:68a9198d0fc122d14bb76837de9aa80cf84caed990b5b237f532ed87d3706736"}, + {file = "lxml-6.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7d47866cb32fb503450b6edc9df355d10dc49836af2e89901bd6ac6b0896d9d9"}, + {file = "lxml-6.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb7c9811bfaa8b1ed5ed319f5d370dfbcaa59d52ea64be2a5a85e18195930354"}, + {file = "lxml-6.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:762ff394d5bd56da0cf034a23dcce4e13923f15321a2adfa2ac00201dc6d3fca"}, + {file = "lxml-6.1.1-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a088f287f7d8275a33c07f2cac6c50b9319309a0200a39e7e75d80c707723099"}, + {file = "lxml-6.1.1-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e902da4b04e6b52e5893900d4b8ab46068f75f3561f01bf1080957f9fd932ed6"}, + {file = "lxml-6.1.1-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1d4962d4c66bf830a7e59ed6cfc17d148149898a3aefa8ec6e59763e6e3ed085"}, + {file = "lxml-6.1.1-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:581d4c8ae690a6609e64862dd6b7c2489635c2d13907fc2b20f2bc200ff1d21e"}, + {file = "lxml-6.1.1-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:876e1ff5930ed8bf295ec5ef9a8155e9b6b1876bbf1deed8b3a8069311875a8f"}, + {file = "lxml-6.1.1-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9eb9b5a968f6e0f6d640092a567e14529ff8cea2e29d00da6f78a79fa49f013c"}, + {file = "lxml-6.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:aa49e06d94aba782c6a02eecb7e507969e7e7a41b267f1b359bb35585f295d5b"}, + {file = "lxml-6.1.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:70cdfd80589d59e43e18005dd7244e8895e93db8ab6a620b7e23df5445a4e3d2"}, + {file = "lxml-6.1.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:aad9aa39483ed8ec44d6d2e59e5b98a0d80676ef0d92f44bfc374836111f62f5"}, + {file = "lxml-6.1.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:d49514be2f28d895c38cf9d2b72d7b9a07d00314519f456c0b50b53cfcf4c785"}, + {file = "lxml-6.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:47402e62c52ff5988c1e8c6c63177f5708bccf48e366dea4e3dcf1e645e04947"}, + {file = "lxml-6.1.1-cp313-cp313-win32.whl", hash = "sha256:3483644525531e1d5762b0c44a8e18b6efba321b6dcf8a8952de10b037618bca"}, + {file = "lxml-6.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:a10bd2fd62e8ce916ececb342f348f190724a098c1faa056fdfb2a22ad5e8660"}, + {file = "lxml-6.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:424aa57aca0897eb922aef34395bd1289b3b6f04e6bae20ea123c0c7e333cffc"}, + {file = "lxml-6.1.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:19b7ab10b210b0b3ad7985d9ac4eb66ab09a90b20fe6e2f7ba55d01a234345d0"}, + {file = "lxml-6.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c08e5c694306507275f2290073350c4f32e383db15213b2c69e7ff39c1193840"}, + {file = "lxml-6.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:74a9717fd0d82effef5c2854f0d917231d5324b5a3eb7275c43ac9fa32f97a14"}, + {file = "lxml-6.1.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efe0374196335f93b53269acd811b944f2e6bdc88e8894f214bd636455484909"}, + {file = "lxml-6.1.1-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac931cdc9442c1763b8a8f6cd62c0c938737eafc5be75eff88df55fc73bc0d00"}, + {file = "lxml-6.1.1-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:aee395f5d0927f947758b4ec119fd5fc8ec71f07a1c5c52077b30b04c0fa6955"}, + {file = "lxml-6.1.1-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9395002973c827b3ed67db77e6ec09f092919a587022174554096a269378fb13"}, + {file = "lxml-6.1.1-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:73bc2086f141224ebddb7fc5c6a36ca58b31b94b561e1dfe8e073e3270fad1e7"}, + {file = "lxml-6.1.1-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:3779def59032b81e44a5f70096ef6bf2082f8d901937dca354474ba09782e245"}, + {file = "lxml-6.1.1-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:86c89b9d55ebf820ad7c90bc533410f0d098054f293351f10603c0c46ff598f5"}, + {file = "lxml-6.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19607c6bbff2a44cf3fe8250abccd20942d3462473e0a721d01d379ed017e462"}, + {file = "lxml-6.1.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:c6ed5141a5c7507cf3ee76bd363b0d6f801e3321adc35b5d825a23115faa5465"}, + {file = "lxml-6.1.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:62aeb7e85b5d60320b9d77eef2e773994e2c0ce10121b277e0a19804e1654a5a"}, + {file = "lxml-6.1.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b1b963fd8f5caa68e99dfae060d54de1fe9cba899b8718b44a00cdca53c3e590"}, + {file = "lxml-6.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:63876be28efefa04a1df615b46770e82042cce445cfdce55160522f57b231ccb"}, + {file = "lxml-6.1.1-cp314-cp314-win32.whl", hash = "sha256:7f7a92e8583f06b1fd49d01158143b8461cfcd135dcb10ec807270a3051bd603"}, + {file = "lxml-6.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:b2d444f2e66624d68e9c6b211e28a76e22fff5fcabcfff4deac18b529b7d4137"}, + {file = "lxml-6.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:3fd9728a2735fda14f4e8235830c86b539e9661e849665bf926d3f867943b4bf"}, + {file = "lxml-6.1.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:787b2496d0dbe8cd180984e8d29e3a6f76e7ea34db781cb3bd55e4ba1ef8b4ee"}, + {file = "lxml-6.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2c8daa471358dc2d6fcf02165e80ec68f77871a286df95bc5cc3816153b0fd2c"}, + {file = "lxml-6.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:acd7d70b64c0aae0c7922cca83d288a16f5f6da523637697872253415269baef"}, + {file = "lxml-6.1.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4f0dd2f01f9f8a89f565d000e03abcf0a13d692a346c8d22f628d49af098777a"}, + {file = "lxml-6.1.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b7e8a14c8634bf6f7a568634cb395305a6d964aeb5b7ee32248094bed3a7e2c"}, + {file = "lxml-6.1.1-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:86281fbdd6a8162756f8d603f37e3435bfa38043adb79c6dc6a2dfee065e7525"}, + {file = "lxml-6.1.1-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5d7152ec39ca7c402d8fb9bad86140a15b9503bd0c54484e3f1bbe3dd37ceca"}, + {file = "lxml-6.1.1-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:88d8cb75b9d82858497a5393e3c63cfbf03035225e4b35a49ed7ccb151e4dc0e"}, + {file = "lxml-6.1.1-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f64ec5397ea6a41fc1b4af0380d79b44a755b5531dcaccd9940fb260dca93038"}, + {file = "lxml-6.1.1-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d34bbf07dbc7ca5970671b1512e928991fb5e9d95365636c9b2d8b4f53af405e"}, + {file = "lxml-6.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:17e0e18d4ad8adbd0399291bc44845b69d9dd68439a3cdebdf35ff902ec05072"}, + {file = "lxml-6.1.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:3ab541146f1f6968c462d6c2ac495148e8cdba2f8347700b2141b6ec5a75bf52"}, + {file = "lxml-6.1.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2a0217714657e023ef4293500f65aa20fce6164c8fd6b08fa5bd4a859fb14b9b"}, + {file = "lxml-6.1.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:05a82eb6e1530a64f26225b55cbd178113bd0b5af1c2b625f25e5296742c26d2"}, + {file = "lxml-6.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9e36f163528fc50cbef305f02a5fd66d404edf7049cdaff211dbc2cba5a7013e"}, + {file = "lxml-6.1.1-cp314-cp314t-win32.whl", hash = "sha256:649dda677cf3bd6ac9ae14007ba0c824ded8ce5808b53fc7431d9140399118c1"}, + {file = "lxml-6.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:793033d6c5cdf33a573f910d9bea14ef8f5771820411d118da8e1182edb53d5e"}, + {file = "lxml-6.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:58bb955caba94e467d2a96da17660d2d704e0675894cba21ab8a775b8621fd1c"}, + {file = "lxml-6.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6689e828a94eee4f139408c337bb198e014724bb8a8c26d3cfac49d119ed69a6"}, + {file = "lxml-6.1.1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bdebcc8a75d38c7598dfb2c9ed852d7a9eb4a10d6e2d0764b919b802bf32ac88"}, + {file = "lxml-6.1.1-cp38-cp38-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8be8ad51249698103d24b0571df35a10990fbe93dd043b6c024172189485f5e3"}, + {file = "lxml-6.1.1-cp38-cp38-manylinux_2_28_i686.whl", hash = "sha256:76447f65250ed2501ead1a1552f5ce8edff159a86f308348e6a9c4acb5e1f1b4"}, + {file = "lxml-6.1.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ffecec8eb889b58ba9be5b95fb1cc78e22ea8eedea38e8736a1568fe1979250e"}, + {file = "lxml-6.1.1-cp38-cp38-win32.whl", hash = "sha256:c674693f055fa2495de12292cb45e9944199d8eaef5a2dec45175c7c61cb73e3"}, + {file = "lxml-6.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:55b03549819867ea141c0202242c4816c82e52ec36e7e648db9d8da5a3dc3ed6"}, + {file = "lxml-6.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9f79d5325907f13e1be0b3e4dacc1049d1dffc4aeee3c995284bea5fe0fab7d"}, + {file = "lxml-6.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:83b6b30eb131da7a75b601f28c5d6971e6ed3e887919bf6b6a1ad3c2df289080"}, + {file = "lxml-6.1.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:441dd227fa0690eb9fc81edabc63cdcefc212bba99b906dcf6e32cc1a9d3e533"}, + {file = "lxml-6.1.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e07c65f443c887bbcf31cc1771d932ecc192a5273943589b3c7572b749f1ffb2"}, + {file = "lxml-6.1.1-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5bec7d03d78d853597d6107854c2310ce3f761fd218fe9fe91d5101fcf6c2efe"}, + {file = "lxml-6.1.1-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9f76acfb5f68ba982635a53fd985a8044be98a35b43232c2a1ee235ffab3e1dd"}, + {file = "lxml-6.1.1-cp39-cp39-manylinux_2_28_i686.whl", hash = "sha256:8d43ca737b20e106e4aebc42b2f3ae19f00ba63d7eb731698ee083d72d15646f"}, + {file = "lxml-6.1.1-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:32ab449a5486f6c758e849bb86710d0e45edc24a04e250c01555f8f5653958f8"}, + {file = "lxml-6.1.1-cp39-cp39-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:53c909b62a0532183542fed00c5a7218258c56292d409bc789886fe1cb04c438"}, + {file = "lxml-6.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:640f97d43d867bcb9c75b3af013b64850756b746cb6bce8ace83b70da3abba9d"}, + {file = "lxml-6.1.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:469e3618338bd7ab5beb412d2439825479fcf0dab99e394ca563dbc4eaf6c834"}, + {file = "lxml-6.1.1-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:aae97dfdb60715c164419ac2532a76d013c3918a665eb6cb7288098b5f349aaf"}, + {file = "lxml-6.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c9a4b821dc7055bf9e05ff5719e18ec501f75c0f0bbfabd573b277559780833d"}, + {file = "lxml-6.1.1-cp39-cp39-win32.whl", hash = "sha256:639f6c857d91d9be29bd7502348d6736dab168b54b5158cd899abf11684dc186"}, + {file = "lxml-6.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:34c2d737beabfe35baada43941ed519251e9a12e779031496bcd5d539fcfd730"}, + {file = "lxml-6.1.1-cp39-cp39-win_arm64.whl", hash = "sha256:07a4a68e286ee7a1ed7dfb8af83e615757c0ccfe9f18c6b4ea6771388d9ba8c9"}, + {file = "lxml-6.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:31033dc34636ea6b7d5cc11b1ddbda78a14de858ba9d3e1ed4b69a3085bc521e"}, + {file = "lxml-6.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3893c14c4b6ac5b2d54ba8cf03e99fe5104e592de491f19bd6b82756c09f8004"}, + {file = "lxml-6.1.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c07da4cebf6889f03ebac8d238f62318e29f495de0aa18a51ea14e61ae907e2e"}, + {file = "lxml-6.1.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f6f0ce10945fab9c4c06ce14e22af9059d1a87493a9af4501a5b0b9187e21cf2"}, + {file = "lxml-6.1.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f8844cd288697c6425c9beba919302241e3278871dc6519515e72b04e987abcf"}, + {file = "lxml-6.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:ed21202aec73cda4d55d1ce57b389aadb90ffb044e6cd1080b8347efe1b1ec84"}, + {file = "lxml-6.1.1.tar.gz", hash = "sha256:ba96ae44888e0185281e937633a743ea90d5a196c6000f82565ebb0580012d40"}, ] [package.extras] @@ -3412,31 +3286,6 @@ html-clean = ["lxml_html_clean"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -[[package]] -name = "markdown-it-py" -version = "4.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version < \"3.14\"" -files = [ - {file = "markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147"}, - {file = "markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "markdown-it-pyrs", "mistletoe (>=1.0,<2.0)", "mistune (>=3.0,<4.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins (>=0.5.0)"] -profiling = ["gprof2dot"] -rtd = ["ipykernel", "jupyter_sphinx", "mdit-py-plugins (>=0.5.0)", "myst-parser", "pyyaml", "sphinx", "sphinx-book-theme (>=1.0,<2.0)", "sphinx-copybutton", "sphinx-design"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions", "requests"] - [[package]] name = "markupsafe" version = "3.0.3" @@ -3444,7 +3293,6 @@ description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version < \"3.14\"" files = [ {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, @@ -3539,83 +3387,71 @@ files = [ [[package]] name = "matplotlib" -version = "3.10.9" +version = "3.11.1" description = "Python plotting package" optional = false -python-versions = ">=3.10" +python-versions = ">=3.11" groups = ["main"] files = [ - {file = "matplotlib-3.10.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77210dce9cb8153dffc967efaae990543392563d5a376d4dd8539bebcb0ed217"}, - {file = "matplotlib-3.10.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1e7698ac9868428e84d2c967424803b2472ff7167d9d6590d4204ed775343c3b"}, - {file = "matplotlib-3.10.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1aa972116abb4c9d201bf245620b433726cb6856f3bef6a78f776a00f5c92d37"}, - {file = "matplotlib-3.10.9-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae2f11957b27ce53497dd4d7b235c4d4f1faf383dfb39d0c5beb833bff883294"}, - {file = "matplotlib-3.10.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b049278ddce116aaa1c1377ebf58adea909132dfce0281cf7e3a1ea9fc2e2c65"}, - {file = "matplotlib-3.10.9-cp310-cp310-win_amd64.whl", hash = "sha256:82834c3c292d24d3a8aae77cd2d20019de69d692a34a970e4fdb8d33e2ea3dda"}, - {file = "matplotlib-3.10.9-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:68cfdcede415f7c8f5577b03303dd94526cdb6d11036cecdc205e08733b2d2bb"}, - {file = "matplotlib-3.10.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfca0129678bd56379db26c52b5d77ed7de314c047492fbdc763aa7501710cfb"}, - {file = "matplotlib-3.10.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e436d155fa8a3399dc62683f8f5d0e2e50d25d0144a73edd73f82eec8f4abfb"}, - {file = "matplotlib-3.10.9-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56fc0bd271b00025c6edfdc7c2dcd247372c8e1544971d62e1dc7c17367e8bf9"}, - {file = "matplotlib-3.10.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5a6104ed666402ba5106d7f36e0e0cdca4e8d7fa4d39708ca88019e2835a2eb"}, - {file = "matplotlib-3.10.9-cp311-cp311-win_amd64.whl", hash = "sha256:d730e984eddf56974c3e72b6129c7ca462ac38dc624338f4b0b23eb23ecba00f"}, - {file = "matplotlib-3.10.9-cp311-cp311-win_arm64.whl", hash = "sha256:51bf0ddbdc598e060d46c16b5590708f81a1624cefbaaf62f6a81bf9285b8c80"}, - {file = "matplotlib-3.10.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f0c3c28d9fbcc1fe7a03be236d73430cf6409c41fb2383a7ac52fe932b072cb1"}, - {file = "matplotlib-3.10.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41cb28c2bd769aa3e98322c6ab09854cbcc52ab69d2759d681bba3e327b2b320"}, - {file = "matplotlib-3.10.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ae20801130378b82d647ff5047c07316295b68dc054ca6b3c13519d0ea624285"}, - {file = "matplotlib-3.10.9-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c63ebcd8b4b169eb2f5c200552ae6b8be8999a005b6b507ed76fb8d7d674fe2"}, - {file = "matplotlib-3.10.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d75d11c949914165976c621b2324f9ef162af7ebf4b057ddf95dd1dba7e5edcf"}, - {file = "matplotlib-3.10.9-cp312-cp312-win_amd64.whl", hash = "sha256:d091f9d758b34aaaaa6331d13574bf01891d903b3dec59bfff458ef7551de5d6"}, - {file = "matplotlib-3.10.9-cp312-cp312-win_arm64.whl", hash = "sha256:10cc5ce06d10231c36f40e875f3c7e8050362a4ee8f0ee5d29a6b3277d57bb42"}, - {file = "matplotlib-3.10.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b580440f1ff81a0e34122051a3dfabb7e4b7f9e380629929bde0eff9af72165f"}, - {file = "matplotlib-3.10.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b1b745c489cd1a77a0dc1120a05dc87af9798faebc913601feb8c73d89bf2d1e"}, - {file = "matplotlib-3.10.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8f3bcac1ca5ed000a6f4337d47ba67dfddf37ed6a46c15fd7f014997f7bf865f"}, - {file = "matplotlib-3.10.9-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a8d66a55def891c33147ba3ba9bfcabf0b526a43764c818acbb4525e5ed0838"}, - {file = "matplotlib-3.10.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d843374407c4017a6403b59c6c81606773d136f3259d5b6da3131bc814542cc2"}, - {file = "matplotlib-3.10.9-cp313-cp313-win_amd64.whl", hash = "sha256:f4399f64b3e94cd500195490972ae1ee81170df1636fa15364d157d5bdd7b921"}, - {file = "matplotlib-3.10.9-cp313-cp313-win_arm64.whl", hash = "sha256:ba7b3b8ef09eab7df0e86e9ae086faa433efbfbdb46afcb3aa16aabf779469a8"}, - {file = "matplotlib-3.10.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:09218df8a93712bd6ea133e83a153c755448cf7868316c531cffcc43f69d1cc9"}, - {file = "matplotlib-3.10.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:82368699727bfb7b0182e1aa13082e3c08e092fa1a25d3e1fd92405bff96f6d4"}, - {file = "matplotlib-3.10.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3225f4e1edcb8c86c884ddf79ebe20ecd0a67d30188f279897554ccd8fded4dc"}, - {file = "matplotlib-3.10.9-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de2445a0c6690d21b7eb6ce071cebad6d40a2e9bdf10d039074a96ba19797b99"}, - {file = "matplotlib-3.10.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b2b9516251cb89ff618d757daec0e2ed1bf21248013844a853d87ef85ab3081d"}, - {file = "matplotlib-3.10.9-cp313-cp313t-win_amd64.whl", hash = "sha256:e9fae004b941b23ff2edcf1567a857ed77bafc8086ffa258190462328434faf8"}, - {file = "matplotlib-3.10.9-cp313-cp313t-win_arm64.whl", hash = "sha256:6b63d9c7c769b88ab81e10dc86e4e0607cf56817b9f9e6cf24b2a5f1693b8e38"}, - {file = "matplotlib-3.10.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:172db52c9e683f5d12eaf57f0f54834190e12581fe1cc2a19595a8f5acb4e77d"}, - {file = "matplotlib-3.10.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97e35e8d39ccc85859095e01a53847432ba9a53ddf7986f7a54a11b73d0e143f"}, - {file = "matplotlib-3.10.9-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aba1615dabe83188e19d4f75a253c6a08423e04c1425e64039f800050a69de6b"}, - {file = "matplotlib-3.10.9-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34cf8167e023ad956c15f36302911d5406bd99a9862c1a8499ea6f7c0e015dc2"}, - {file = "matplotlib-3.10.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59476c6d29d612b8e9bb6ce8c5b631be6ba8f9e3a2421f22a02b192c7dd28716"}, - {file = "matplotlib-3.10.9-cp314-cp314-win_amd64.whl", hash = "sha256:336b9acc64d309063126edcdaca00db9373af3c476bb94388fe9c5a53ad13e6f"}, - {file = "matplotlib-3.10.9-cp314-cp314-win_arm64.whl", hash = "sha256:2dc9477819ffd78ad12a20df1d9d6a6bd4fec6aaa9072681465fddca052f1456"}, - {file = "matplotlib-3.10.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:da4e09638420548f31c354032a6250e473c68e5a4e96899b4844cf39ddea23fe"}, - {file = "matplotlib-3.10.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:345f6f68ecc8da0ca56fad2ea08fde1a115eda530079eca185d50a7bc3e146c6"}, - {file = "matplotlib-3.10.9-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4edcfbd8565339aa62f1cd4012f7180926fdbe71850f7b0d3c379c175cd6b66c"}, - {file = "matplotlib-3.10.9-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6be157fe17fc37cb95ac1d7374cf717ce9259616edec911a78d9d26dae8522d4"}, - {file = "matplotlib-3.10.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4e42042d54db34fda4e95a7bd3e5789c2a995d2dad3eb8850232ee534092fbbf"}, - {file = "matplotlib-3.10.9-cp314-cp314t-win_amd64.whl", hash = "sha256:c27df8b3848f32a83d1767566595e43cfaa4460380974da06f4279a7ec143c39"}, - {file = "matplotlib-3.10.9-cp314-cp314t-win_arm64.whl", hash = "sha256:a49f1eadc84ca85fd72fa4e89e70e61bf86452df6f971af04b12c60761a0772c"}, - {file = "matplotlib-3.10.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1872fb212a05b729e649754a72d5da61d03e0554d76e80303b6f83d1d2c0552b"}, - {file = "matplotlib-3.10.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:985f2238880e2e69093f588f5fe2e46771747febf0649f3cf7f7b7480875317f"}, - {file = "matplotlib-3.10.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6640f75af2c6148293caa0a2b39dd806a492dd66c8a8b04035813e33d0fd2585"}, - {file = "matplotlib-3.10.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:42fb814efabe95c06c1994d8ab5a8385f43a249e23badd3ba931d4308e5bca20"}, - {file = "matplotlib-3.10.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f76e640a5268850bfda54b5131b1b1941cc685e42c5fa98ed9f2d64038308cba"}, - {file = "matplotlib-3.10.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3fc0364dfbe1d07f6d15c5ebd0c5bf89e126916e5a8667dd4a7a6e84c36653d4"}, - {file = "matplotlib-3.10.9.tar.gz", hash = "sha256:fd66508e8c6877d98e586654b608a0456db8d7e8a546eb1e2600efd957302358"}, + {file = "matplotlib-3.11.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b7cf158e7add54a8d51ac9b5a84abd6d4e13ed4951b4f25f1c5139f41c2addb2"}, + {file = "matplotlib-3.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2ace7273b9a5061a3b420918a16fae1f2dc5dfee1abcc13aba71b5d94b1820c"}, + {file = "matplotlib-3.11.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee55e9041211bf84302ab55ec3965df18dd90ae19f8b58332a7feaf208bfe83"}, + {file = "matplotlib-3.11.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f4bdeea33a8d15a071dbfe6d119451b1d719c733ac666d65357082901a9099"}, + {file = "matplotlib-3.11.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b4c78ceb2f11bcac7389d305cda17aeb1f4586a857854ab5780bd3dd8dbfc407"}, + {file = "matplotlib-3.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:7f33a781e12b1e53b278deb2f5373c2e55ec4f10727be3440c0cfb5cda9f944f"}, + {file = "matplotlib-3.11.1-cp311-cp311-win_arm64.whl", hash = "sha256:67e4c3cd578c65ebd81bdc09a1b6592ceafee6dfafe116dc85dfcb647b5bbb18"}, + {file = "matplotlib-3.11.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e15ef41507f3d525f46154ac9e3ae785dacde9f20e593a25de8986267892ef74"}, + {file = "matplotlib-3.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:21a67b961a6d597bca54fae826cd20695ba4a6e4d05424a08da6e13e3176fd6b"}, + {file = "matplotlib-3.11.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba8f811b8ddfac493734d6af0b2dff96919d0c28ca0d641858dab4262777c6ea"}, + {file = "matplotlib-3.11.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c52f7ad20ef476806ed212380b1d54d20310c8b86bdc2c9a68b51f0024a44472"}, + {file = "matplotlib-3.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8b14eb22961fe865efb0e4ff167e333e428908b00115a8d800ccb65ee108e481"}, + {file = "matplotlib-3.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:88a2a27dd9691ae448dfae4b26f59036be90c3c28757edd3553a29559d00859f"}, + {file = "matplotlib-3.11.1-cp312-cp312-win_arm64.whl", hash = "sha256:480194afceca4df2f137c2721227d3cba67121fbf4397b69cee7f83714b0a58a"}, + {file = "matplotlib-3.11.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6771b0cd7838c6a857a7209814158c0ad09bfef878db3033dd82d70ad101f191"}, + {file = "matplotlib-3.11.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2abdee5ffa2fe11b2d19f7a5c63b785fb7c28cc46c7bc1814156341d9d1a33e1"}, + {file = "matplotlib-3.11.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0a19dcf73406d3746d25a5ed42d713604c9a3e024d129b102852b0d941cb9f3"}, + {file = "matplotlib-3.11.1-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7389b77ed2ab0552f46d9a90b81b7b8e6dfcdc42adc36c37a0865799843e0e3e"}, + {file = "matplotlib-3.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c90be0b73568da4f662afac580956a76e308437e641b4a45aa08925eeb67d95f"}, + {file = "matplotlib-3.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:68408341f2312836fbbdf6b3c78047f65b2d8752f5fd221c3e72d348f5b34f8b"}, + {file = "matplotlib-3.11.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c1f44890d435c1b4ef52f701ad5828cb450ea97bcc83918fda6be74965d6cd2"}, + {file = "matplotlib-3.11.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:5e510088c27a89d53580a752f959146893563e63c330e161d159b0fee652af6f"}, + {file = "matplotlib-3.11.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:1524e2bdd48a93557aa47ddcfe9c225dfdd57d5a01a5c49128c20f0632980ee1"}, + {file = "matplotlib-3.11.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:11664c551345553db92e61cae6cf1376f138f8c47cafdf13b64b18f3e3e9e464"}, + {file = "matplotlib-3.11.1-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e1f8922ba31959cf6a9dfb51be64b7f7bc582801a3957dc0c2f3afcd3537adf"}, + {file = "matplotlib-3.11.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83235693abde86e5e0129998f80ee39fc7f58e6d56a88fafb28a9278833e9d5f"}, + {file = "matplotlib-3.11.1-cp313-cp313t-win_amd64.whl", hash = "sha256:9a076f4fc5cdc43fdf510f5981418d25c2db4973418d9f22d8bb3dc8045ada78"}, + {file = "matplotlib-3.11.1-cp313-cp313t-win_arm64.whl", hash = "sha256:216fbb93a74add02ddb4cb38ef5348f59ac00b3e84567eaf16598772d40e150a"}, + {file = "matplotlib-3.11.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:30c492d4ba9448595b6fd8708c6725963f8148e25c0d8842948da5b05f0ee8d3"}, + {file = "matplotlib-3.11.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ac104be2768ffdd8655db9e71b768cbb45f2b9aa7b450cf1595e8f65d3822319"}, + {file = "matplotlib-3.11.1-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be943cb68bc6660ead58c55b3aa6366cba2ef7feb06460fbcce32360376f19f"}, + {file = "matplotlib-3.11.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5af0dcda57d471440a7b5b623e70e0a61003518443d9098f211a96ecfbbc25be"}, + {file = "matplotlib-3.11.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3d3fd84082b1afbd9398466c81309e20045be20d48fe0fb18c43504d164cbbb2"}, + {file = "matplotlib-3.11.1-cp314-cp314-win_amd64.whl", hash = "sha256:9601a1e90be21e4884c53b4f3dc3ee0544654946f9975258d691f1c2e2f119c6"}, + {file = "matplotlib-3.11.1-cp314-cp314-win_arm64.whl", hash = "sha256:ae30c6109848ac0f9fa36c5d6270938487614c47ba31860bd5361266dabc5685"}, + {file = "matplotlib-3.11.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:dadfe80797174e2984aae3be0b77594a3c72d2c0a40fbd4a0de48d2728caf3ae"}, + {file = "matplotlib-3.11.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:89b193b255f4f6f7948dbcee3691f4f341ab05d9a8874a67b45ddb4182922eda"}, + {file = "matplotlib-3.11.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:191163532cdefcb1571ca38a6d7e6474baccde64495783e6ba47aa07ec4b9bbb"}, + {file = "matplotlib-3.11.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9fdf1c818ab05d0e74002091ddaf414478a3a449ec9d51c8976d45be7e3a01e2"}, + {file = "matplotlib-3.11.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b937b9dba5f5f6c1e31c47abe2186c865c0914fd18f2ce0dfc39c9adcef5951d"}, + {file = "matplotlib-3.11.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f2912f647f3fbe1ccf085f91e213936f9101bead81a5e670565b1f1b3712f4fb"}, + {file = "matplotlib-3.11.1-cp314-cp314t-win_arm64.whl", hash = "sha256:54d47b8ae8b579633a3902ca5b4ad6c1e132a5626d64447b2e22a66394e79987"}, + {file = "matplotlib-3.11.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:427258425f9a3fc4ed79a91f9e9b9aaf5a82cb6571e85dc14063cc6fbb993741"}, + {file = "matplotlib-3.11.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:1ac697e591c11b6ad04679a73c2d2f9980fe9d9f0311fb414a2e329706343dfb"}, + {file = "matplotlib-3.11.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e4b9ac2f1f607ecda2af90a5232beee2af7582fce1cc30c4b6a1b012dc21ee99"}, + {file = "matplotlib-3.11.1.tar.gz", hash = "sha256:69647db5746941c793d6e445a4cd349323ffb87d9cc958c2ad84a659b4832d30"}, ] [package.dependencies] contourpy = ">=1.0.1" cycler = ">=0.10" -fonttools = ">=4.22.0" +fonttools = ">=4.28.2" kiwisolver = ">=1.3.1" -numpy = ">=1.23" +numpy = ">=1.25" packaging = ">=20.0" -pillow = ">=8" +pillow = ">=9" pyparsing = ">=3" python-dateutil = ">=2.7" -[package.extras] -dev = ["meson-python (>=0.13.1,<0.17.0)", "pybind11 (>=2.13.2,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7,<10)"] - [[package]] name = "mccabe" version = "0.7.0" @@ -3670,29 +3506,16 @@ cli = ["python-dotenv (>=1.0.0)", "typer (>=0.16.0)"] rich = ["rich (>=13.9.4)"] ws = ["websockets (>=15.0.1)"] -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version < \"3.14\"" -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - [[package]] name = "mistralai" -version = "2.6.0" +version = "2.7.2" description = "Python Client SDK for the Mistral AI API." optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "mistralai-2.6.0-py3-none-any.whl", hash = "sha256:4b7202b0cab84ea03f8ff4a933c8cfc615b3057520d9d76467c07aa23939dab2"}, - {file = "mistralai-2.6.0.tar.gz", hash = "sha256:531a86292ad498fc0fcd6dfcd480a3f4db9e92f558e14ffb22172824831e3a6e"}, + {file = "mistralai-2.7.2-py3-none-any.whl", hash = "sha256:b2b26fa43670d6247ea352c23fe821605ecbbcf305755b629e804dbd3f6fd439"}, + {file = "mistralai-2.7.2.tar.gz", hash = "sha256:184b7a502e69cc7cdeb0b095020d7e9407a9544c4496f0317984263dac3d7939"}, ] [package.dependencies] @@ -3712,8 +3535,8 @@ realtime = ["websockets (>=13.0)"] telemetry = ["opentelemetry-exporter-otlp-proto-http (>=1.33.1,<2.0.0)", "opentelemetry-sdk (>=1.33.1,<2.0.0)"] workflow-payload-compression = ["msgpack (>=1.1.0,<2.0.0)", "zstandard (>=0.25.0,<0.26)"] workflow-payload-encryption = ["cryptography (>=41.0.0,<47.0.0)"] -workflow-payload-offloading = ["aioboto3 (>=12.4.0,<13.0.0)", "azure-identity[aio] (>=1.25.0,<2.0.0)", "azure-storage-blob[aio] (>=12.28.0,<13.0.0)", "gcloud-aio-storage (>=9.3.0,<10.0.0)"] -workflow-payload-offloading-azure = ["azure-identity[aio] (>=1.25.0,<2.0.0)", "azure-storage-blob[aio] (>=12.28.0,<13.0.0)"] +workflow-payload-offloading = ["aioboto3 (>=12.4.0,<13.0.0)", "azure-identity (>=1.25.0,<2.0.0)", "azure-storage-blob[aio] (>=12.28.0,<13.0.0)", "gcloud-aio-storage (>=9.3.0,<10.0.0)"] +workflow-payload-offloading-azure = ["azure-identity (>=1.25.0,<2.0.0)", "azure-storage-blob[aio] (>=12.28.0,<13.0.0)"] workflow-payload-offloading-gcs = ["gcloud-aio-storage (>=9.3.0,<10.0.0)"] workflow-payload-offloading-s3 = ["aioboto3 (>=12.4.0,<13.0.0)"] @@ -3952,61 +3775,62 @@ files = [ [[package]] name = "mypy" -version = "2.1.0" +version = "2.3.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "mypy-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:11a6beb180257a805961aea9ec591bbd0bd17f1e18d35b8456d57aee5bedfedc"}, - {file = "mypy-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ef78c1d306bbf9a8a12f526c44902c9c28dffd6c52c52bf6a72641ce18d3849"}, - {file = "mypy-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c209a90853081ff01d01ee895cafe10f7db1474e0d95beaeef0f6c1db9119bbd"}, - {file = "mypy-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47cebf61abde7c088a4e27718a8b13a81655686b2e9c251f5c0915a802248166"}, - {file = "mypy-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d57a90ae5e872138a425ec328edbc9b235d1934c4377881a33ec05b341acc9a8"}, - {file = "mypy-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:aea7f7a8a55b459c34275fc468ada6ca7c173a5e43a68f5dbe588a563d8a06b8"}, - {file = "mypy-2.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c989640253f0d76843e9c6c1bbf4bd48c5e85ada61bde4beb37cb3eca035685e"}, - {file = "mypy-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a683016b16fe2f572dc04c72be7ee0504ac1605a265d0200f5cea695fb788f41"}, - {file = "mypy-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a293c534adb55271fef24a26da04b855540a8c13cc07bc5917b9fd2c394f2ca"}, - {file = "mypy-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7406f4d048e71e576f5356d317e5b0a9e666dfd966bd99f9d14ca06e1a341538"}, - {file = "mypy-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0210d626fc8b31ccc90233754c7bc90e1f43205e85d96387f7db1285b55c398"}, - {file = "mypy-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3712c20deed54e814eaaa825603bada8ea1c390670a397c95b98405347acc563"}, - {file = "mypy-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fcaa0e479066e31f7cceb6a3bea39cb22b2ff51a6b2f24f193d19179ba17c389"}, - {file = "mypy-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:0b1a5260c95aa443083f9ed3592662941951bca3d4ca224a5dc517c38b7cf666"}, - {file = "mypy-2.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:244358bf1c0da7722230bce60683d52e8e9fd030554926f15b747a84efb5b3af"}, - {file = "mypy-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4ec7c57657493c7a75534df2751c8ae2cda383c16ecc55d2106c54476b1b16f6"}, - {file = "mypy-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8161b6ff4392410023224f0969d17db93e1e154bc3e4ba62598e720723ae211"}, - {file = "mypy-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf03e12003084a67395184d3eb8cbd6a489dc3655b5664b28c210a9e2403ab0b"}, - {file = "mypy-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:20509760fd791c51579d573153407d226385ec1f8bcce55d730b354f3336bc22"}, - {file = "mypy-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:6753d0c1fdd6b1a23b9e4f283ce80b2153b724adcb2653b20b85a8a28ac6436b"}, - {file = "mypy-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:98ebb6589bb3b6d0c6f0c459d53ca55b8091fbc13d277c4041c885392e8195e8"}, - {file = "mypy-2.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35aac3bb114e03888f535d5eb51b8bafbb3266586b599da1940f9b1be3ec5bd5"}, - {file = "mypy-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8de55a8c861f2a49331f807be98d90caeceeef520bde13d43a160207f8af613e"}, - {file = "mypy-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fdf2941a07434af755837d9880f7d7d25f1dacb1af9dcd4b9b66f2220a3024e"}, - {file = "mypy-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e195b817c13f02352a9c124301f9f30f078405444679b6753c1b96b6eed37285"}, - {file = "mypy-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5431d42af987ebd92ba2f71d45c85ed41d8e6ca9f5fd209a69f68f707d2469e5"}, - {file = "mypy-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:767fe8c66dc3e01e19e1737d4c38ebefead16125e1b8e58ad421903b376f5c65"}, - {file = "mypy-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:ecfe70d43775ab99562ab128ce49854a362044c9f894961f68f898c23cb7429d"}, - {file = "mypy-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7354c5a7f69d9345c3d6e69921d57088eea3ddeeb6b20d34c1b3855b02c36ec2"}, - {file = "mypy-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:49890d4f76ac9e06ec117f9e09f3174da70a620a0c300953d8595c926e80947f"}, - {file = "mypy-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:761be68e023ef5d94678772396a8af1220030f80837a3afd8d0aef3b419666f4"}, - {file = "mypy-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c90345fc182dc363b891350457ec69c35140858538f38b4540845afcc32b1aef"}, - {file = "mypy-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b84802e7b5a6daf1f5e15bc9fcd7ddae77be13981ffab037f1c67bb84d67d135"}, - {file = "mypy-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:022c771234936ceac541ebaf836fe9e2abeb3f5e09aff21588fe543ff006fe21"}, - {file = "mypy-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:498207db725cec88829a6a5c2fc771205fd043719ef98bc49aba8fb9fc4e6d57"}, - {file = "mypy-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d5e5cad0efeba72b93cd17490cc0d69c5ac9ca132994fe3fb0314808aeeb83e"}, - {file = "mypy-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ff715050c127d724fd260a2e666e7747fdd83511c0c47d449d98238970aef780"}, - {file = "mypy-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82208da9e09414d520e912d3e462d454854bed0810b71540bb016dcbca7308fd"}, - {file = "mypy-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e79ebc1b904b84f0310dff7469655a9c36c7a68bddb37bdd42b67a332df61d08"}, - {file = "mypy-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e583edc957cfb0deb142079162ae826f58449b116c1d442f2d91c69d9fced081"}, - {file = "mypy-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b33b6cd332695bba180d55e717a79d3038e479a2c49cc5eb3d53603409b9a5d7"}, - {file = "mypy-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4f910fe825376a7b66ef7ca8c98e5a149e8cd64c19ae71d84047a74ee060d4e6"}, - {file = "mypy-2.1.0-py3-none-any.whl", hash = "sha256:a663814603a5c563fb87a4f96fb473eeb30d1f5a4885afcf44f9db000a366289"}, - {file = "mypy-2.1.0.tar.gz", hash = "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633"}, -] - -[package.dependencies] -ast-serialize = ">=0.3.0,<1.0.0" -librt = {version = ">=0.11.0", markers = "platform_python_implementation != \"PyPy\""} + {file = "mypy-2.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1fa8d916ac3b705af733c4c1e6c9ebe38fd0d52beb15b105c3e8355b55e6ecdc"}, + {file = "mypy-2.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:28e1e2af8cd8fff551fd30f2fe4b03fb76764ac8b1ba6c6a1bd00ad32b412db3"}, + {file = "mypy-2.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3e77244df3843048c3f927182916730e40c124cbaa43905c1fb86cb382aa0805"}, + {file = "mypy-2.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9559ab18a9c9957dfa3004ab57cd4bac5f26a724329a9584e583367f0c2e1117"}, + {file = "mypy-2.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:09abd66d8685e73f8f7d17b847c3e104d9a7b164a8706ea87d6c96a3d45816d5"}, + {file = "mypy-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e91adad1ca81742ac7ef9893959911df867752206b37135185e88dfb3c89494"}, + {file = "mypy-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:6f99ec626e3c3a2f7c0b22c5b90ddb5dabb1c18729c971e9bdaca1f1766d2cee"}, + {file = "mypy-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3419d00717afbc5265b50dd14b1278f29ea4884dd398ab67873489ac093fd329"}, + {file = "mypy-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cfca8ee88544090f86b6dcce05ec55d66eb48a762412ac2507810ba4bd793b6f"}, + {file = "mypy-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75cbb4b9ef04a0c84a957f07abc4504fbf64b8dcc145675101f2d3a78a4b1d6a"}, + {file = "mypy-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:982e3d53dd23d0a4cef67dd66791fdbede0cf38f9eb617bf47663554c51e1e36"}, + {file = "mypy-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:85c5385b93012ffa3b31479ab579aef5415f4f3a32c6cf1ae07a984d2a0ff461"}, + {file = "mypy-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:13b1b16e2fa39f3b2e33fb1c468abc7a69369fa2e886b4b87b5afc81472325cd"}, + {file = "mypy-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:b5cd2f027a972a4a5f2278a11fac9747f5f81a53a30b714d74950b6807e55568"}, + {file = "mypy-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d53fc67b9d28a43c6199077f49fea0f05839e36cf6158500331c9549225e5a5"}, + {file = "mypy-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fbc00cee7bdbb9291979ddc9d08034a29dfcda4932628c9bbc28c1edd589df0c"}, + {file = "mypy-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:04e617030eca5221909c8b7d8d7fd1c637948199aa2100b2ad9813feb07e1491"}, + {file = "mypy-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56c184d2c20ca6b6378d58d1960270a767f41f5e44acbbd27f05effef4f4e1d7"}, + {file = "mypy-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3961a4a34b05f7c74b0f05aa51fbfe99a2d1e126038df40318d15c8f558b7ef3"}, + {file = "mypy-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:b1942b9314d4c784b8ea1dbab4972603290e5dd5630f06675f13aec97526bc4c"}, + {file = "mypy-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:be51653d7669d7d7955d613b8d0bb57d5b652eaf71a873ddf65ac87254dd2595"}, + {file = "mypy-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:91ad22a52ae2c7e621c2f67c94d5a17f66b3209a4cff5cf8a573579835c69e97"}, + {file = "mypy-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:99ac767cc5d3b64c8d0ae226ead10c96694f94e4e7da1668642225dcd4e75aac"}, + {file = "mypy-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6d2c484742a4d7b0ed6d07b143375624d3b899c5749c7b3c947f56261f48a6"}, + {file = "mypy-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7da939dd335cfd2ad788bdfd081c9f4e47634ab995e5a45eb15fd1e5bc052f8b"}, + {file = "mypy-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7247eb2824f996722a949530183394921ca71deb9680052a338cf53cff7925c2"}, + {file = "mypy-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:75b0984bb3cbd76bb5c9291a8671f7ae66ca3b51c7584c358fc2e923259f0757"}, + {file = "mypy-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:d78fcf900b59cb7e82cb7e3a235e31b462d9333d92285bd1e4952d355b8ffba1"}, + {file = "mypy-2.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ea317b060ce83e26050f8f9e4d7d6bf44ed7597c8ff9990bccffbb9d1d8522db"}, + {file = "mypy-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:094af99f92638aa92852326188b85a89e50f4a472f44827c03362228482f0762"}, + {file = "mypy-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de121747278144fc9ae7caa2e978cf5df12aebc82933182f5b3b86081a30baef"}, + {file = "mypy-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37fa4de896a84e2dc9200d91e614c22563b43d1a266789d4bbac7b22ebe6192b"}, + {file = "mypy-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f1b3a98dfd21058bc759bb3337d5d1f61d0fdf9f3cf9c00f4291790fb5427bff"}, + {file = "mypy-2.3.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:944c665d984157cb96a679dfb7a4a81dd1d36b24b9c284b699514e6e626b82d4"}, + {file = "mypy-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:4359424140d985192c778c1ce2c114a10c1ca58a381ed79cfa70d37df94b299f"}, + {file = "mypy-2.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:3dd0bed92c4bdec57c42505b96416fb9e6a5aa7be84d2809bcd5f2ecec2860d7"}, + {file = "mypy-2.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:691fdc37132b1ae628d834f672e74de83462d9fb4aff621835767fb43a8dd373"}, + {file = "mypy-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:aec15d465d477558fd842757b487849007311cf3897849cdda0e3162ac0ac556"}, + {file = "mypy-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b352b7e49f5e6576009e8df730e1ff4f915cb565b851b396d2ffe2f5a6f5da88"}, + {file = "mypy-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c6c6bf687b17f90dbfcad95b960d32eaa0154c00da45f03ab50bf8952e047fe"}, + {file = "mypy-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f4ed18f111bfe2d599bca7468e7f9251042c1c2118f762c8de2766a56d773c60"}, + {file = "mypy-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0b025a93cffb9781d231f232be07a17912f35f10a313c24f301c81e842870654"}, + {file = "mypy-2.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:adebc76aab4f3495a88b41d48aa4aff0c03f2822501da76625afcca5975f19e5"}, + {file = "mypy-2.3.0-py3-none-any.whl", hash = "sha256:6b1cdb579446b60432432b2b2403a6201b4b475a004d7f488511c9ba177c9e88"}, + {file = "mypy-2.3.0.tar.gz", hash = "sha256:465965d41cd9a2726694e983e8ce7113259327bec798115d1e1dfa2a52fb666e"}, +] + +[package.dependencies] +ast-serialize = ">=0.6.0,<1.0.0" +librt = {version = ">=0.13.0", markers = "platform_python_implementation != \"PyPy\""} mypy_extensions = ">=1.0.0" pathspec = ">=1.0.0" typing_extensions = [ @@ -4099,97 +3923,69 @@ sqlalchemy = ["sqlalchemy (>=2.0)"] [[package]] name = "numpy" -version = "2.4.4" +version = "2.5.1" description = "Fundamental package for array computing in Python" optional = false -python-versions = ">=3.11" +python-versions = ">=3.12" groups = ["main", "dev"] files = [ - {file = "numpy-2.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db"}, - {file = "numpy-2.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0"}, - {file = "numpy-2.4.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015"}, - {file = "numpy-2.4.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40"}, - {file = "numpy-2.4.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d"}, - {file = "numpy-2.4.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502"}, - {file = "numpy-2.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd"}, - {file = "numpy-2.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5"}, - {file = "numpy-2.4.4-cp311-cp311-win32.whl", hash = "sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e"}, - {file = "numpy-2.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e"}, - {file = "numpy-2.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e"}, - {file = "numpy-2.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b"}, - {file = "numpy-2.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e"}, - {file = "numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842"}, - {file = "numpy-2.4.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8"}, - {file = "numpy-2.4.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121"}, - {file = "numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e"}, - {file = "numpy-2.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44"}, - {file = "numpy-2.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d"}, - {file = "numpy-2.4.4-cp312-cp312-win32.whl", hash = "sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827"}, - {file = "numpy-2.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a"}, - {file = "numpy-2.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec"}, - {file = "numpy-2.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50"}, - {file = "numpy-2.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115"}, - {file = "numpy-2.4.4-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af"}, - {file = "numpy-2.4.4-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c"}, - {file = "numpy-2.4.4-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103"}, - {file = "numpy-2.4.4-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83"}, - {file = "numpy-2.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed"}, - {file = "numpy-2.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959"}, - {file = "numpy-2.4.4-cp313-cp313-win32.whl", hash = "sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed"}, - {file = "numpy-2.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf"}, - {file = "numpy-2.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d"}, - {file = "numpy-2.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5"}, - {file = "numpy-2.4.4-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7"}, - {file = "numpy-2.4.4-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93"}, - {file = "numpy-2.4.4-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e"}, - {file = "numpy-2.4.4-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40"}, - {file = "numpy-2.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e"}, - {file = "numpy-2.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392"}, - {file = "numpy-2.4.4-cp313-cp313t-win32.whl", hash = "sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008"}, - {file = "numpy-2.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8"}, - {file = "numpy-2.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233"}, - {file = "numpy-2.4.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0"}, - {file = "numpy-2.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a"}, - {file = "numpy-2.4.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a"}, - {file = "numpy-2.4.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b"}, - {file = "numpy-2.4.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a"}, - {file = "numpy-2.4.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d"}, - {file = "numpy-2.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252"}, - {file = "numpy-2.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f"}, - {file = "numpy-2.4.4-cp314-cp314-win32.whl", hash = "sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc"}, - {file = "numpy-2.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74"}, - {file = "numpy-2.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb"}, - {file = "numpy-2.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e"}, - {file = "numpy-2.4.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113"}, - {file = "numpy-2.4.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d"}, - {file = "numpy-2.4.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d"}, - {file = "numpy-2.4.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f"}, - {file = "numpy-2.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0"}, - {file = "numpy-2.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150"}, - {file = "numpy-2.4.4-cp314-cp314t-win32.whl", hash = "sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871"}, - {file = "numpy-2.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e"}, - {file = "numpy-2.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7"}, - {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4"}, - {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e"}, - {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c"}, - {file = "numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3"}, - {file = "numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7"}, - {file = "numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f"}, - {file = "numpy-2.4.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119"}, - {file = "numpy-2.4.4.tar.gz", hash = "sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0"}, + {file = "numpy-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c889b56fe48b1018f764b0eec8df59ab654e9148aa91faa12596043500de277"}, + {file = "numpy-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab451b59c5643c570974c43aef780703ef1d3b4965d2be07afd530615a9358d1"}, + {file = "numpy-2.5.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:78798bd5b9ad744056af8efa90e3b9ddaa53272a0848a483084a1cc0a13b2dc0"}, + {file = "numpy-2.5.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2ae0ca40bcb22d6ba59c1dfd5446f49940b0f2d821fde133f10dda11f816b84e"}, + {file = "numpy-2.5.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61ac47e772e6b8ea489e1d2f441a34c5c3ac17327e7ce294cbdf535795ad4e75"}, + {file = "numpy-2.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59fda5e192b570217ec2580c96f00e9a7e12ef6866a900eb089b62c1a32545ca"}, + {file = "numpy-2.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f7119ebff1a9829e9f431a4f9d28e703023bb6b9fe7c8f724467dbfc27c94ab3"}, + {file = "numpy-2.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e824c2acf8862052246be5a44c15da1777940c60d010dd2aab897824d9c430f9"}, + {file = "numpy-2.5.1-cp312-cp312-win32.whl", hash = "sha256:08d60c810432eb83360958dea0999ac4cfb94531ea8efcbf0b7f277c2068aeb2"}, + {file = "numpy-2.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:f7d60026c0bdb1380e83bfa7a0419c4577ee4b9a08880afcb6dadeb74c649fa2"}, + {file = "numpy-2.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:17a25e09640602e10bc8de0e6fa2b3fd68eedd84ba6d7842dc8f32f9ab87bd0b"}, + {file = "numpy-2.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0bfebd8695f9863592fe744be833a258120b14a9f39da255e8aa8fade2c0ddd1"}, + {file = "numpy-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:30b44a6b53a7ae63c54c089a8726e5563ed302716c5b7ccc85afade40b0e7ff6"}, + {file = "numpy-2.5.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:6165343f81b56ef8f514f396989e529b61d9dc709b99421b07e9f3e698e2287d"}, + {file = "numpy-2.5.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4939237038ada79308dda3204ac6462df056b5672b2e25db1149cf873668b3e1"}, + {file = "numpy-2.5.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c6759f538fb912fc46de0a6b1758ccf7b57bc7c7ebebc23974fdac3de8db0cd"}, + {file = "numpy-2.5.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9726558e8db4a5bf7929a70ae50f63abda4daf0efe810e3bfbab95976f75fc1a"}, + {file = "numpy-2.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3935f3b419b244a02732676fa5317a9193cc596a4c0646db07e5b421229ac9f7"}, + {file = "numpy-2.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc932a65ded7ce9013d120845a2514dcccb1a67bfc8deb8d37633762951904a6"}, + {file = "numpy-2.5.1-cp313-cp313-win32.whl", hash = "sha256:4b4ff1608417eb7a59da7b967bbb798cacfe071d2caf526a24281cd562072ed9"}, + {file = "numpy-2.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:6c3fe51bc6a16453d452997053454f309e8e0ed7b42d6b361ce4ac8c32913d74"}, + {file = "numpy-2.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:f7feb014281029e628ba2d5a007407443b06e418b6fe451d1e2adcbc8eba0107"}, + {file = "numpy-2.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7c786fe9a5bbe360022e584c5a34cf6b54265c71bd7ec8ac3d8fec38968071f8"}, + {file = "numpy-2.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32985c896d897419ef8da6917872d80b78ad0ea26d85b23245c7366ffde76d75"}, + {file = "numpy-2.5.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:efd736408cc97c79b9e6917338dfc8f06013b2274f992e96b1d9a81a71e2a2c2"}, + {file = "numpy-2.5.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ab84dc6b074fa881cae55bea94cc4f68e285181ba7f32497bf7dee6b1496165b"}, + {file = "numpy-2.5.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caf3e317d33d60c37986b452613f4ab51246d0691350c03d0cb4a898627f4a95"}, + {file = "numpy-2.5.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54ad769f17bc2d833b620851989f62054fb9ab93c969d9e1dc3c8e3d56beea21"}, + {file = "numpy-2.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c12afb53450fa976d4c681c50a7423729a4c51c0465ed9f32b8a9cabbc472373"}, + {file = "numpy-2.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c11c405efc5ff6816d5983c96cdfa215bab3428961243af3ff59b228490438"}, + {file = "numpy-2.5.1-cp314-cp314-win32.whl", hash = "sha256:f2479a47f8d5932d1718168a681ad6e536a9df484c83cfcf9de365e164537ace"}, + {file = "numpy-2.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:24d0eb82c0541d3415a33425db64ae439dffccd7b4dbcb30e7c35120205c506a"}, + {file = "numpy-2.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:5a4c988b38d261deeeaad9954e3deb091ad905c94e8bb6708654ef1d97f286b0"}, + {file = "numpy-2.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a33276be12fa045805f477f22482088b66bb758ffbe89a9d21457de863a32e22"}, + {file = "numpy-2.5.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:f089d7b00756190aacf1f5d34bdf38c3c430ac82b4f868f8cede73380460fce7"}, + {file = "numpy-2.5.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:09e9bfd8d2cf479c7d174804fb3811c53a8e9f20a37444008606b57d6b7a826d"}, + {file = "numpy-2.5.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e68d8dd1e7eba712948f2053a29ec86917bc70ba1358df869d9f06649ef9cf09"}, + {file = "numpy-2.5.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99d5095fa265a0c4152e7bb12759e14381ef5496152f1ce58f44bdf55c44beb4"}, + {file = "numpy-2.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ab87a91b3cc3382b8956095bd8f95e00cf679bb81554339be1a2ba404a1473c1"}, + {file = "numpy-2.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:224ca51130ef7da85bea2191625181cb4f337f9cb64b471f10c1a12aa8b60077"}, + {file = "numpy-2.5.1-cp314-cp314t-win32.whl", hash = "sha256:6eab239876581b2b3c5a242281b6007bbdbcd1c7085d7709bb57c5929b11e6bf"}, + {file = "numpy-2.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:83ce9c80d5b521b0d77ddcbe5447c218d247929b6cc056ca5351342accfff0af"}, + {file = "numpy-2.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:5a6db61f9aaa57e369905c67d852045d3c4f7126405b29d09b19dec118e9c9cb"}, + {file = "numpy-2.5.1.tar.gz", hash = "sha256:a48a113e6afea91f5608793bafa7ef2ad481fefbda87ec5069f483de61cb9fa3"}, ] [[package]] name = "openai" -version = "2.24.0" +version = "2.48.0" description = "The official Python library for the openai API" optional = false python-versions = ">=3.9" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "openai-2.24.0-py3-none-any.whl", hash = "sha256:fed30480d7d6c884303287bde864980a4b137b60553ffbcf9ab4a233b7a73d94"}, - {file = "openai-2.24.0.tar.gz", hash = "sha256:1e5769f540dbd01cb33bc4716a23e67b9d695161a734aff9c5f925e2bf99a673"}, + {file = "openai-2.48.0-py3-none-any.whl", hash = "sha256:c98df30aaaf93c51979f64d3e7c5b76464f8be0173368266229eb8fe6bd30f2c"}, + {file = "openai-2.48.0.tar.gz", hash = "sha256:231b1e7661dda14574986c2f71451e9d584b7fe69e0ee6480e12ed090b48fc16"}, ] [package.dependencies] @@ -4200,11 +3996,13 @@ jiter = ">=0.10.0,<1" pydantic = ">=1.9.0,<3" sniffio = "*" tqdm = ">4" -typing-extensions = ">=4.11,<5" +typing-extensions = ">=4.14,<5" [package.extras] -aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.9)"] +aiohttp = ["aiohttp (>=3.14.1) ; python_version >= \"3.10\"", "httpx-aiohttp (>=0.1.9) ; python_version >= \"3.10\""] +bedrock = ["botocore (>=1.40.0,<1.43) ; python_version < \"3.10\"", "botocore (>=1.40.0,<2) ; python_version >= \"3.10\""] datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] +httpx2 = ["anyio (>=4.10.0,<5) ; python_version >= \"3.10\"", "httpx (>=0.25.1,<1) ; python_version >= \"3.10\"", "httpx2 (>=2.7.0,<3) ; python_version >= \"3.10\""] realtime = ["websockets (>=13,<16)"] voice-helpers = ["numpy (>=2.0.2)", "sounddevice (>=0.5.1)"] @@ -4284,60 +4082,54 @@ files = [ [[package]] name = "pandas" -version = "3.0.2" +version = "3.0.5" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.11" groups = ["main"] files = [ - {file = "pandas-3.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a727a73cbdba2f7458dc82449e2315899d5140b449015d822f515749a46cbbe0"}, - {file = "pandas-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbbd4aa20ca51e63b53bbde6a0fa4254b1aaabb74d2f542df7a7959feb1d760c"}, - {file = "pandas-3.0.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:339dda302bd8369dedeae979cb750e484d549b563c3f54f3922cb8ff4978c5eb"}, - {file = "pandas-3.0.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:61c2fd96d72b983a9891b2598f286befd4ad262161a609c92dc1652544b46b76"}, - {file = "pandas-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c934008c733b8bbea273ea308b73b3156f0181e5b72960790b09c18a2794fe1e"}, - {file = "pandas-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:60a80bb4feacbef5e1447a3f82c33209c8b7e07f28d805cfd1fb951e5cb443aa"}, - {file = "pandas-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:ed72cb3f45190874eb579c64fa92d9df74e98fd63e2be7f62bce5ace0ade61df"}, - {file = "pandas-3.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:f12b1a9e332c01e09510586f8ca9b108fd631fd656af82e452d7315ef6df5f9f"}, - {file = "pandas-3.0.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:232a70ebb568c0c4d2db4584f338c1577d81e3af63292208d615907b698a0f18"}, - {file = "pandas-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:970762605cff1ca0d3f71ed4f3a769ea8f85fc8e6348f6e110b8fea7e6eb5a14"}, - {file = "pandas-3.0.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aff4e6f4d722e0652707d7bcb190c445fe58428500c6d16005b02401764b1b3d"}, - {file = "pandas-3.0.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef8b27695c3d3dc78403c9a7d5e59a62d5464a7e1123b4e0042763f7104dc74f"}, - {file = "pandas-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f8d68083e49e16b84734eb1a4dcae4259a75c90fb6e2251ab9a00b61120c06ab"}, - {file = "pandas-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:32cc41f310ebd4a296d93515fcac312216adfedb1894e879303987b8f1e2b97d"}, - {file = "pandas-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:a4785e1d6547d8427c5208b748ae2efb64659a21bd82bf440d4262d02bfa02a4"}, - {file = "pandas-3.0.2-cp312-cp312-win_arm64.whl", hash = "sha256:08504503f7101300107ecdc8df73658e4347586db5cfdadabc1592e9d7e7a0fd"}, - {file = "pandas-3.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b5918ba197c951dec132b0c5929a00c0bf05d5942f590d3c10a807f6e15a57d3"}, - {file = "pandas-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d606a041c89c0a474a4702d532ab7e73a14fe35c8d427b972a625c8e46373668"}, - {file = "pandas-3.0.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:710246ba0616e86891b58ab95f2495143bb2bc83ab6b06747c74216f583a6ac9"}, - {file = "pandas-3.0.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5d3cfe227c725b1f3dff4278b43d8c784656a42a9325b63af6b1492a8232209e"}, - {file = "pandas-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c3b723df9087a9a9a840e263ebd9f88b64a12075d1bf2ea401a5a42f254f084d"}, - {file = "pandas-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a3096110bf9eac0070b7208465f2740e2d8a670d5cb6530b5bb884eca495fd39"}, - {file = "pandas-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:07a10f5c36512eead51bc578eb3354ad17578b22c013d89a796ab5eee90cd991"}, - {file = "pandas-3.0.2-cp313-cp313-win_arm64.whl", hash = "sha256:5fdbfa05931071aba28b408e59226186b01eb5e92bea2ab78b65863ca3228d84"}, - {file = "pandas-3.0.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:dbc20dea3b9e27d0e66d74c42b2d0c1bed9c2ffe92adea33633e3bedeb5ac235"}, - {file = "pandas-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b75c347eff42497452116ce05ef461822d97ce5b9ff8df6edacb8076092c855d"}, - {file = "pandas-3.0.2-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1478075142e83a5571782ad007fb201ed074bdeac7ebcc8890c71442e96adf7"}, - {file = "pandas-3.0.2-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5880314e69e763d4c8b27937090de570f1fb8d027059a7ada3f7f8e98bdcb677"}, - {file = "pandas-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b5329e26898896f06035241a626d7c335daa479b9bbc82be7c2742d048e41172"}, - {file = "pandas-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:81526c4afd31971f8b62671442a4b2b51e0aa9acc3819c9f0f12a28b6fcf85f1"}, - {file = "pandas-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:7cadd7e9a44ec13b621aec60f9150e744cfc7a3dd32924a7e2f45edff31823b0"}, - {file = "pandas-3.0.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:db0dbfd2a6cdf3770aa60464d50333d8f3d9165b2f2671bcc299b72de5a6677b"}, - {file = "pandas-3.0.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0555c5882688a39317179ab4a0ed41d3ebc8812ab14c69364bbee8fb7a3f6288"}, - {file = "pandas-3.0.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:01f31a546acd5574ef77fe199bc90b55527c225c20ccda6601cf6b0fd5ed597c"}, - {file = "pandas-3.0.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:deeca1b5a931fdf0c2212c8a659ade6d3b1edc21f0914ce71ef24456ca7a6535"}, - {file = "pandas-3.0.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0f48afd9bb13300ffb5a3316973324c787054ba6665cda0da3fbd67f451995db"}, - {file = "pandas-3.0.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6c4d8458b97a35717b62469a4ea0e85abd5ed8687277f5ccfc67f8a5126f8c53"}, - {file = "pandas-3.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:b35d14bb5d8285d9494fe93815a9e9307c0876e10f1e8e89ac5b88f728ec8dcf"}, - {file = "pandas-3.0.2-cp314-cp314-win_arm64.whl", hash = "sha256:63d141b56ef686f7f0d714cfb8de4e320475b86bf4b620aa0b7da89af8cbdbbb"}, - {file = "pandas-3.0.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:140f0cffb1fa2524e874dde5b477d9defe10780d8e9e220d259b2c0874c89d9d"}, - {file = "pandas-3.0.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ae37e833ff4fed0ba352f6bdd8b73ba3ab3256a85e54edfd1ab51ae40cca0af8"}, - {file = "pandas-3.0.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d888a5c678a419a5bb41a2a93818e8ed9fd3172246555c0b37b7cc27027effd"}, - {file = "pandas-3.0.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b444dc64c079e84df91baa8bf613d58405645461cabca929d9178f2cd392398d"}, - {file = "pandas-3.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4544c7a54920de8eeacaa1466a6b7268ecfbc9bc64ab4dbb89c6bbe94d5e0660"}, - {file = "pandas-3.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:734be7551687c00fbd760dc0522ed974f82ad230d4a10f54bf51b80d44a08702"}, - {file = "pandas-3.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:57a07209bebcbcf768d2d13c9b78b852f9a15978dac41b9e6421a81ad4cdd276"}, - {file = "pandas-3.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:5371b72c2d4d415d08765f32d689217a43227484e81b2305b52076e328f6f482"}, - {file = "pandas-3.0.2.tar.gz", hash = "sha256:f4753e73e34c8d83221ba58f232433fca2748be8b18dbca02d242ed153945043"}, + {file = "pandas-3.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2946e77e4a53cd248cbde631a12f0e51c8324ce354c3eba4d20147c1ad6f4282"}, + {file = "pandas-3.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71ecc8fb7ed1a7aa4392316b5309a6347e8e7f832f38fd897846b3a1457a9298"}, + {file = "pandas-3.0.5-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b173f5951ff6b8b0ec7675e20dff3c97b7e7a57dfcce387c2d7c5afe87cb7899"}, + {file = "pandas-3.0.5-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2c0cf1dd9b55a22d105fc46c1b489af3bd42264fcba7c66297bf47a9a1d9c78a"}, + {file = "pandas-3.0.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0fac0010c75e4efb6b99e249c183a8993ce0dc95c240f9b120a5e67c727b7928"}, + {file = "pandas-3.0.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:08d24fe11a17dc33bd6e937dc9c665f9cba08fbdc9f657f405713515febe300d"}, + {file = "pandas-3.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:b1261758dfb6cf12c3cff8300e21cefad30e7ec709abb4c24ac7318e6a52462a"}, + {file = "pandas-3.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:679f4e85b30ddb1515458ab1e788d3e260eae369b1f78da7a3aa4cac8ebf4a2a"}, + {file = "pandas-3.0.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fa290c16964d4963fbfbc358928239cf3bd755b20e988ce944877def2f44471d"}, + {file = "pandas-3.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c2e26bb46934b8a2ca0c3de1d3d606fc5f6746584791b2db264d58cf370e08dc"}, + {file = "pandas-3.0.5-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:73fa87b08a7ef706f8aafda39ddaccf2a99047bea62d8c88a0361bcafb2237bc"}, + {file = "pandas-3.0.5-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d373ce03ffd84010ed9839fa73672a9c8256990532e158440c0085db7d914b34"}, + {file = "pandas-3.0.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2a29c53d85ea98c5e792c59ef82ee9fbe6ca902c0d0adb6b23f45ef894cd7bf6"}, + {file = "pandas-3.0.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a5ad3b02ed6bc7d7ae9b70804b2c6aa31827489d150f8e623ce82491b82085d7"}, + {file = "pandas-3.0.5-cp312-cp312-pyemscripten_2024_0_wasm32.whl", hash = "sha256:b2acb4650527eec6822c3dadb2b771277b65e7dae7a267d4bccf65fd1bb3fbce"}, + {file = "pandas-3.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:80a611068e8a3ac23f7398c6c14eb46dc974e5cc9997f653e2dcfd1da74edd41"}, + {file = "pandas-3.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:25ff585b972a18ef1fe9ffa3ac6544d9950508aa76832e5147640b6022821e49"}, + {file = "pandas-3.0.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c1c05a767fe8e5b4fe9e1c29806829c582052eaedb9120a3da83ba3f69e24a5b"}, + {file = "pandas-3.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b86765f268b56f7e665b93bce9d5df69dee7f99e595cf8fb839483ab315942a3"}, + {file = "pandas-3.0.5-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c597ecf5616b5c420372c1d4d4c00dbbfba7398bea857dcc984347e1ea48417b"}, + {file = "pandas-3.0.5-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4b11c36e218331d0387cbe3a0a5f75162357a1d92d57b2b08a336ff94b19b2be"}, + {file = "pandas-3.0.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf52e1f61d229496da17dc7ab54acdee627357e7008fd4fecba3d0ba2937fa58"}, + {file = "pandas-3.0.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:db172144bb56422bd157812f3b021eacc255451470b31e2c633c349490a1cfee"}, + {file = "pandas-3.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:0d298e951f23016ce4699951d044ae6418dbc91bf68cefca0f77666fcbb4e5c6"}, + {file = "pandas-3.0.5-cp313-cp313-win_arm64.whl", hash = "sha256:66266d3442a5e8b3c90274c2b8b230bee42dd1c286bc822cc2f9f2c7e12b883e"}, + {file = "pandas-3.0.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2f264fc46911cc8131a7322a16199bbf8e353d27c10bb211f5bd0c814324dc36"}, + {file = "pandas-3.0.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:53730687fcd161883b24e10411c06d6a4c0f2275d2faf3bb2bc25deb4ba8007c"}, + {file = "pandas-3.0.5-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:960d3ebcf249f75206899fcd2c6de53f736b7265759ced0d3e559df0b8b709b0"}, + {file = "pandas-3.0.5-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e94c2c5ca43bd3ca32bf64d32308887b65e5f9bfd8023ea52755107a999f93b"}, + {file = "pandas-3.0.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e819dd5f62966b481a8cb649d3299ebd886a1ea91ed5a99bf7ce77c98d18ab94"}, + {file = "pandas-3.0.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3c5ed2e7c06e91d340dfd091d7934f9bc82e4a36b95f647f090b9d1c9ac649da"}, + {file = "pandas-3.0.5-cp314-cp314-win_amd64.whl", hash = "sha256:cd8f7c6dc98527058ee6264219343f5392240a6f1bfa654fc5d79023020d0c92"}, + {file = "pandas-3.0.5-cp314-cp314-win_arm64.whl", hash = "sha256:5183427f5a8156d480f30333777bc978be93650a49a7c01db26adffe95b31e85"}, + {file = "pandas-3.0.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:303da736987d481074ca720ada325f8bd80c64ebc2d45ed79b29df3aaa4a26ca"}, + {file = "pandas-3.0.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3b2801bbb049d0136f6c213eae02b5fca969384fc2064dd728d8620552aa49da"}, + {file = "pandas-3.0.5-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cce3a9d11d2b1f82c69a27ec1f4948a170e2c403c4bbfa8cca62e3fdebe2ef3a"}, + {file = "pandas-3.0.5-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef01af4d8dc6cd2c8d6c7736f149574ef93fe043811eeb5e445f2647154b5040"}, + {file = "pandas-3.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e2759e890db96dfcffdbd9b86c3c2cb6afaf58def482820317e06163ec1066cd"}, + {file = "pandas-3.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b58b1b39d46a5862e3fb18f50d1a201398619d16a0f9f73f57eea5583cf0e63c"}, + {file = "pandas-3.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:1c10461f6eeb35d8f05b6184c65c8b9991663b66c46b1d559b682cb34ae7c6ea"}, + {file = "pandas-3.0.5-cp314-cp314t-win_arm64.whl", hash = "sha256:3c5015fd1730fbf883647e88068176c839c102cea883ba1769a6f4593bfc1f8c"}, + {file = "pandas-3.0.5.tar.gz", hash = "sha256:dca3734d6ab7c906e6730f0788b0a1dbb9f2467731f9711f77995c8e9d62d712"}, ] [package.dependencies] @@ -4349,7 +4141,7 @@ python-dateutil = ">=2.8.2" tzdata = {version = "*", markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\""} [package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)", "beautifulsoup4 (>=4.12.3)", "bottleneck (>=1.4.2)", "fastparquet (>=2024.11.0)", "fsspec (>=2024.10.0)", "gcsfs (>=2024.10.0)", "html5lib (>=1.1)", "hypothesis (>=6.116.0)", "jinja2 (>=3.1.5)", "lxml (>=5.3.0)", "matplotlib (>=3.9.3)", "numba (>=0.60.0)", "numexpr (>=2.10.2)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "psycopg2 (>=2.9.10)", "pyarrow (>=13.0.0)", "pyiceberg (>=0.8.1)", "pymysql (>=1.1.1)", "pyreadstat (>=1.2.8)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)", "python-calamine (>=0.3.0)", "pytz (>=2024.2)", "pyxlsb (>=1.0.10)", "qtpy (>=2.4.2)", "s3fs (>=2024.10.0)", "scipy (>=1.14.1)", "tables (>=3.10.1)", "tabulate (>=0.9.0)", "xarray (>=2024.10.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)", "zstandard (>=0.23.0)"] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)", "beautifulsoup4 (>=4.12.3)", "bottleneck (>=1.4.2)", "fastparquet (>=2024.11.0)", "fsspec (>=2024.10.0)", "gcsfs (>=2024.10.0)", "html5lib (>=1.1)", "hypothesis (>=6.116.0)", "jinja2 (>=3.1.5)", "lxml (>=5.3.0)", "matplotlib (>=3.9.3)", "numba (>=0.60.0)", "numexpr (>=2.10.2)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.5)", "psycopg2 (>=2.9.10)", "pyarrow (>=13.0.0)", "pyiceberg (>=0.8.1)", "pymysql (>=1.1.1)", "pyreadstat (>=1.2.8)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)", "python-calamine (>=0.3.0)", "pytz (>=2020.1)", "pyxlsb (>=1.0.10)", "qtpy (>=2.4.2)", "s3fs (>=2024.10.0)", "scipy (>=1.14.1)", "tables (>=3.10.1)", "tabulate (>=0.9.0)", "xarray (>=2024.10.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.2.0)", "zstandard (>=0.23.0)"] aws = ["s3fs (>=2024.10.0)"] clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.4.2)"] compression = ["zstandard (>=0.23.0)"] @@ -4370,8 +4162,8 @@ postgresql = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "psyc pyarrow = ["pyarrow (>=13.0.0)"] spss = ["pyreadstat (>=1.2.8)"] sql-other = ["SQLAlchemy (>=2.0.36)", "adbc-driver-postgresql (>=1.2.0)", "adbc-driver-sqlite (>=1.2.0)"] -test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4)", "pytest-xdist (>=3.6.1)"] -timezone = ["pytz (>=2024.2)"] +test = ["hypothesis (>=6.116.0)", "pytest (>=8.3.4,<9.1)", "pytest-xdist (>=3.6.1)"] +timezone = ["pytz (>=2020.1)"] xml = ["lxml (>=5.3.0)"] [[package]] @@ -4423,14 +4215,14 @@ pillow = "*" [[package]] name = "pdfminer-six" -version = "20251230" +version = "20260107" description = "PDF parser and analyzer" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "pdfminer_six-20251230-py3-none-any.whl", hash = "sha256:9ff2e3466a7dfc6de6fd779478850b6b7c2d9e9405aa2a5869376a822771f485"}, - {file = "pdfminer_six-20251230.tar.gz", hash = "sha256:e8f68a14c57e00c2d7276d26519ea64be1b48f91db1cdc776faa80528ca06c1e"}, + {file = "pdfminer_six-20260107-py3-none-any.whl", hash = "sha256:366585ba97e80dffa8f00cebe303d2f381884d8637af4ce422f1df3ef38111a9"}, + {file = "pdfminer_six-20260107.tar.gz", hash = "sha256:96bfd431e3577a55a0efd25676968ca4ce8fd5b53f14565f85716ff363889602"}, ] [package.dependencies] @@ -4442,120 +4234,116 @@ image = ["Pillow"] [[package]] name = "pdfplumber" -version = "0.11.9" +version = "0.11.10" description = "Plumb a PDF for detailed information about each char, rectangle, and line." optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "pdfplumber-0.11.9-py3-none-any.whl", hash = "sha256:33ec5580959ba524e9100138746e090879504c42955df1b8a997604dd326c443"}, - {file = "pdfplumber-0.11.9.tar.gz", hash = "sha256:481224b678b2bbdbf376e2c39bf914144eef7c3d301b4a28eebf0f7f6109d6dc"}, + {file = "pdfplumber-0.11.10-py3-none-any.whl", hash = "sha256:7741ea81bf165b474b153e6789d10d18e06b6ddcf3ec84289c3ef2fed6802580"}, + {file = "pdfplumber-0.11.10.tar.gz", hash = "sha256:b95b2d28c66efb0a794a83b88c6c6aea5987532a445d20a1cbcfa657022e6e57"}, ] [package.dependencies] -"pdfminer.six" = "20251230" -Pillow = ">=9.1" -pypdfium2 = ">=4.18.0" +"pdfminer.six" = "20260107" +Pillow = ">=12.2.0" +pypdfium2 = ">=5.9.0" [[package]] name = "pillow" -version = "12.2.0" +version = "12.3.0" description = "Python Imaging Library (fork)" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "pillow-12.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f"}, - {file = "pillow-12.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97"}, - {file = "pillow-12.2.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff"}, - {file = "pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec"}, - {file = "pillow-12.2.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136"}, - {file = "pillow-12.2.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c"}, - {file = "pillow-12.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3"}, - {file = "pillow-12.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa"}, - {file = "pillow-12.2.0-cp310-cp310-win32.whl", hash = "sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032"}, - {file = "pillow-12.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5"}, - {file = "pillow-12.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024"}, - {file = "pillow-12.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab"}, - {file = "pillow-12.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65"}, - {file = "pillow-12.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7"}, - {file = "pillow-12.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e"}, - {file = "pillow-12.2.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705"}, - {file = "pillow-12.2.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176"}, - {file = "pillow-12.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b"}, - {file = "pillow-12.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909"}, - {file = "pillow-12.2.0-cp311-cp311-win32.whl", hash = "sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808"}, - {file = "pillow-12.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60"}, - {file = "pillow-12.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe"}, - {file = "pillow-12.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5"}, - {file = "pillow-12.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421"}, - {file = "pillow-12.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987"}, - {file = "pillow-12.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76"}, - {file = "pillow-12.2.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005"}, - {file = "pillow-12.2.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780"}, - {file = "pillow-12.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5"}, - {file = "pillow-12.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5"}, - {file = "pillow-12.2.0-cp312-cp312-win32.whl", hash = "sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940"}, - {file = "pillow-12.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5"}, - {file = "pillow-12.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414"}, - {file = "pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c"}, - {file = "pillow-12.2.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2"}, - {file = "pillow-12.2.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c"}, - {file = "pillow-12.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795"}, - {file = "pillow-12.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f"}, - {file = "pillow-12.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed"}, - {file = "pillow-12.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9"}, - {file = "pillow-12.2.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed"}, - {file = "pillow-12.2.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3"}, - {file = "pillow-12.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9"}, - {file = "pillow-12.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795"}, - {file = "pillow-12.2.0-cp313-cp313-win32.whl", hash = "sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e"}, - {file = "pillow-12.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b"}, - {file = "pillow-12.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06"}, - {file = "pillow-12.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b"}, - {file = "pillow-12.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f"}, - {file = "pillow-12.2.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612"}, - {file = "pillow-12.2.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c"}, - {file = "pillow-12.2.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea"}, - {file = "pillow-12.2.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4"}, - {file = "pillow-12.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4"}, - {file = "pillow-12.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea"}, - {file = "pillow-12.2.0-cp313-cp313t-win32.whl", hash = "sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24"}, - {file = "pillow-12.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98"}, - {file = "pillow-12.2.0-cp313-cp313t-win_arm64.whl", hash = "sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453"}, - {file = "pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8"}, - {file = "pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b"}, - {file = "pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295"}, - {file = "pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed"}, - {file = "pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae"}, - {file = "pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601"}, - {file = "pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be"}, - {file = "pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f"}, - {file = "pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286"}, - {file = "pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50"}, - {file = "pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104"}, - {file = "pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7"}, - {file = "pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150"}, - {file = "pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1"}, - {file = "pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463"}, - {file = "pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3"}, - {file = "pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166"}, - {file = "pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe"}, - {file = "pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd"}, - {file = "pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e"}, - {file = "pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06"}, - {file = "pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43"}, - {file = "pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354"}, - {file = "pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1"}, - {file = "pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1"}, - {file = "pillow-12.2.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e"}, - {file = "pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5"}, + {file = "pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a"}, + {file = "pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7"}, + {file = "pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f"}, + {file = "pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec"}, + {file = "pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468"}, + {file = "pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed"}, + {file = "pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1"}, + {file = "pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb"}, + {file = "pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f"}, + {file = "pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756"}, + {file = "pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6"}, + {file = "pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd"}, + {file = "pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd"}, + {file = "pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c"}, + {file = "pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5"}, + {file = "pillow-12.3.0-cp311-cp311-win32.whl", hash = "sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b"}, + {file = "pillow-12.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a"}, + {file = "pillow-12.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26"}, + {file = "pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965"}, + {file = "pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7"}, + {file = "pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9"}, + {file = "pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91"}, + {file = "pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c"}, + {file = "pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df"}, + {file = "pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f"}, + {file = "pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09"}, + {file = "pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace"}, + {file = "pillow-12.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec"}, + {file = "pillow-12.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66"}, + {file = "pillow-12.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35"}, + {file = "pillow-12.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65"}, + {file = "pillow-12.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3"}, + {file = "pillow-12.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a"}, + {file = "pillow-12.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e"}, + {file = "pillow-12.3.0-cp313-cp313-win32.whl", hash = "sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f"}, + {file = "pillow-12.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8"}, + {file = "pillow-12.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217"}, + {file = "pillow-12.3.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930"}, + {file = "pillow-12.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8"}, + {file = "pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0"}, + {file = "pillow-12.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321"}, + {file = "pillow-12.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b"}, + {file = "pillow-12.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198"}, + {file = "pillow-12.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130"}, + {file = "pillow-12.3.0-cp314-cp314-win32.whl", hash = "sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a"}, + {file = "pillow-12.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d"}, + {file = "pillow-12.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838"}, + {file = "pillow-12.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e"}, + {file = "pillow-12.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17"}, + {file = "pillow-12.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385"}, + {file = "pillow-12.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c"}, + {file = "pillow-12.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d"}, + {file = "pillow-12.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931"}, + {file = "pillow-12.3.0-cp314-cp314t-win32.whl", hash = "sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7"}, + {file = "pillow-12.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c"}, + {file = "pillow-12.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402"}, + {file = "pillow-12.3.0-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c"}, + {file = "pillow-12.3.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f"}, + {file = "pillow-12.3.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701"}, + {file = "pillow-12.3.0-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace"}, + {file = "pillow-12.3.0-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4"}, + {file = "pillow-12.3.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39"}, + {file = "pillow-12.3.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71"}, + {file = "pillow-12.3.0-cp315-cp315-win32.whl", hash = "sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827"}, + {file = "pillow-12.3.0-cp315-cp315-win_amd64.whl", hash = "sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5"}, + {file = "pillow-12.3.0-cp315-cp315-win_arm64.whl", hash = "sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658"}, + {file = "pillow-12.3.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf"}, + {file = "pillow-12.3.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64"}, + {file = "pillow-12.3.0-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e"}, + {file = "pillow-12.3.0-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777"}, + {file = "pillow-12.3.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1"}, + {file = "pillow-12.3.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9"}, + {file = "pillow-12.3.0-cp315-cp315t-win32.whl", hash = "sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8"}, + {file = "pillow-12.3.0-cp315-cp315t-win_amd64.whl", hash = "sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418"}, + {file = "pillow-12.3.0-cp315-cp315t-win_arm64.whl", hash = "sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3"}, + {file = "pillow-12.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a"}, + {file = "pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce"}, ] [package.extras] @@ -4563,19 +4351,19 @@ docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybut fpx = ["olefile"] mic = ["olefile"] test-arrow = ["arro3-compute", "arro3-core", "nanoarrow", "pyarrow"] -tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma (>=5)", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] +tests = ["coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "setuptools", "trove-classifiers (>=2024.10.12)"] xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.9.6" +version = "4.11.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917"}, - {file = "platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a"}, + {file = "platformdirs-4.11.0-py3-none-any.whl", hash = "sha256:360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74"}, + {file = "platformdirs-4.11.0.tar.gz", hash = "sha256:0555d18370482847566ffabcaa53ad7c6c1c29f195989ae1ed634a05f76ea1e0"}, ] [[package]] @@ -4594,18 +4382,6 @@ files = [ dev = ["pre-commit", "tox"] testing = ["coverage", "pytest", "pytest-benchmark"] -[[package]] -name = "ply" -version = "3.11" -description = "Python Lex & Yacc" -optional = false -python-versions = "*" -groups = ["main"] -files = [ - {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"}, - {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, -] - [[package]] name = "portalocker" version = "3.2.0" @@ -4628,14 +4404,14 @@ tests = ["coverage-conditional-plugin (>=0.9.0)", "portalocker[redis]", "pytest [[package]] name = "pre-commit" -version = "4.6.0" +version = "4.6.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b"}, - {file = "pre_commit-4.6.0.tar.gz", hash = "sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9"}, + {file = "pre_commit-4.6.1-py2.py3-none-any.whl", hash = "sha256:0e3b2942510d1fb34eec167a3ec57331bf8442122f1153a9fb8b58f5c49b2717"}, + {file = "pre_commit-4.6.1.tar.gz", hash = "sha256:03e809865c7d178b9979d06c761fcbfe6808fdaded8581a745bb110e52050421"}, ] [package.dependencies] @@ -4647,162 +4423,161 @@ virtualenv = ">=20.10.0" [[package]] name = "prompt-toolkit" -version = "3.0.52" +version = "3.0.53" description = "Library for building powerful interactive command lines in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955"}, - {file = "prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855"}, + {file = "prompt_toolkit-3.0.53-py3-none-any.whl", hash = "sha256:01c0891d7f9237d5e339f7d3e42cdae80b7534abb1c7c0e3352efba6231492f2"}, + {file = "prompt_toolkit-3.0.53.tar.gz", hash = "sha256:9ec8a0ad96d5c56148b3f914aa79c1564c3fde5d2e6b876e7bc327e353cf8fa6"}, ] [package.dependencies] -wcwidth = "*" +wcwidth = ">=0.1.4" [[package]] name = "propcache" -version = "0.4.1" +version = "0.5.2" description = "Accelerated property cache" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db"}, - {file = "propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8"}, - {file = "propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925"}, - {file = "propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21"}, - {file = "propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5"}, - {file = "propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db"}, - {file = "propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7"}, - {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4"}, - {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60"}, - {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f"}, - {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900"}, - {file = "propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c"}, - {file = "propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb"}, - {file = "propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37"}, - {file = "propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581"}, - {file = "propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf"}, - {file = "propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5"}, - {file = "propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e"}, - {file = "propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566"}, - {file = "propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165"}, - {file = "propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc"}, - {file = "propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48"}, - {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570"}, - {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85"}, - {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e"}, - {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757"}, - {file = "propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f"}, - {file = "propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1"}, - {file = "propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6"}, - {file = "propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239"}, - {file = "propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2"}, - {file = "propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403"}, - {file = "propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207"}, - {file = "propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72"}, - {file = "propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367"}, - {file = "propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4"}, - {file = "propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf"}, - {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3"}, - {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778"}, - {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6"}, - {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9"}, - {file = "propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75"}, - {file = "propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8"}, - {file = "propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db"}, - {file = "propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1"}, - {file = "propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf"}, - {file = "propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311"}, - {file = "propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74"}, - {file = "propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe"}, - {file = "propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af"}, - {file = "propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c"}, - {file = "propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f"}, - {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1"}, - {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24"}, - {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa"}, - {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61"}, - {file = "propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66"}, - {file = "propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81"}, - {file = "propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e"}, - {file = "propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1"}, - {file = "propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b"}, - {file = "propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566"}, - {file = "propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835"}, - {file = "propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e"}, - {file = "propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859"}, - {file = "propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b"}, - {file = "propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0"}, - {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af"}, - {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393"}, - {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874"}, - {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7"}, - {file = "propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1"}, - {file = "propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717"}, - {file = "propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37"}, - {file = "propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a"}, - {file = "propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12"}, - {file = "propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c"}, - {file = "propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded"}, - {file = "propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641"}, - {file = "propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4"}, - {file = "propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44"}, - {file = "propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d"}, - {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b"}, - {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e"}, - {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f"}, - {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49"}, - {file = "propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144"}, - {file = "propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f"}, - {file = "propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153"}, - {file = "propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992"}, - {file = "propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f"}, - {file = "propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393"}, - {file = "propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0"}, - {file = "propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a"}, - {file = "propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be"}, - {file = "propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc"}, - {file = "propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a"}, - {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89"}, - {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726"}, - {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367"}, - {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36"}, - {file = "propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455"}, - {file = "propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85"}, - {file = "propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1"}, - {file = "propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9"}, - {file = "propcache-0.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3d233076ccf9e450c8b3bc6720af226b898ef5d051a2d145f7d765e6e9f9bcff"}, - {file = "propcache-0.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:357f5bb5c377a82e105e44bd3d52ba22b616f7b9773714bff93573988ef0a5fb"}, - {file = "propcache-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cbc3b6dfc728105b2a57c06791eb07a94229202ea75c59db644d7d496b698cac"}, - {file = "propcache-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:182b51b421f0501952d938dc0b0eb45246a5b5153c50d42b495ad5fb7517c888"}, - {file = "propcache-0.4.1-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b536b39c5199b96fc6245eb5fb796c497381d3942f169e44e8e392b29c9ebcc"}, - {file = "propcache-0.4.1-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:db65d2af507bbfbdcedb254a11149f894169d90488dd3e7190f7cdcb2d6cd57a"}, - {file = "propcache-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd2dbc472da1f772a4dae4fa24be938a6c544671a912e30529984dd80400cd88"}, - {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:daede9cd44e0f8bdd9e6cc9a607fc81feb80fae7a5fc6cecaff0e0bb32e42d00"}, - {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:71b749281b816793678ae7f3d0d84bd36e694953822eaad408d682efc5ca18e0"}, - {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:0002004213ee1f36cfb3f9a42b5066100c44276b9b72b4e1504cddd3d692e86e"}, - {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:fe49d0a85038f36ba9e3ffafa1103e61170b28e95b16622e11be0a0ea07c6781"}, - {file = "propcache-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:99d43339c83aaf4d32bda60928231848eee470c6bda8d02599cc4cebe872d183"}, - {file = "propcache-0.4.1-cp39-cp39-win32.whl", hash = "sha256:a129e76735bc792794d5177069691c3217898b9f5cee2b2661471e52ffe13f19"}, - {file = "propcache-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:948dab269721ae9a87fd16c514a0a2c2a1bdb23a9a61b969b0f9d9ee2968546f"}, - {file = "propcache-0.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:5fd37c406dd6dc85aa743e214cef35dc54bbdd1419baac4f6ae5e5b1a2976938"}, - {file = "propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237"}, - {file = "propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d"}, + {file = "propcache-0.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a81be28596d6559f6131ef33e10200de6e17643b3c74ce03f9eb103be6ae8b"}, + {file = "propcache-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29cbaac5ea0212663e6845e04b5e188d5a6ae6dd919810ac835bf1d3b42c3f4c"}, + {file = "propcache-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bf3be92233808fcd338eba0fb4d0b59ec5772af4f4ecfcec450d1bfc0f8b5eb"}, + {file = "propcache-0.5.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f8ea531c794b9d6274acd4e8d2c2ebcac590a4361d27482edd3010b79f1325e"}, + {file = "propcache-0.5.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:decfca4c79dd53ebab484b00cc4b6717d8c369f86e74aa4ca395a64ac651495e"}, + {file = "propcache-0.5.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4621064bbf28fa77ff64dd5d94367c04684c67d3a5bf1dff25f0cd0d98a38f3b"}, + {file = "propcache-0.5.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b96db7141a592cbc968daf1feea83a118e6ab378af4abbc72b248c895414c22d"}, + {file = "propcache-0.5.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1ca071adabaab6e9219924bbe00af821f1ee7de113a9eca1cdc292de3d120f4d"}, + {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e4294d04a94dcab1b3bccd8b66d962dcad411a1d19414b2a41d1445f1de32ad0"}, + {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a0e399a2eccb91ed18721f86aa85757727400b6865c89e88934781deb9c8498b"}, + {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:823581fd5cb08b12a48bfa11fe962a7916766b6170c17b028fbdf762b85eb9bf"}, + {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:949c91d1a990cf3b2e8188dfcfb25005e0b834a06c63fa4ef9f360878ce21ecf"}, + {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:cc1177027eda740fdb152706bd215a3f124e3eea15afc39f2cb9fe351b50619e"}, + {file = "propcache-0.5.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b05d643f944a8c3c4bd86d65ffd87bf3264b617f87791940302bc474d2ff5274"}, + {file = "propcache-0.5.2-cp310-cp310-win32.whl", hash = "sha256:8114f28879e0904748e831c3a7774261bd9e75f49be089f389a76f959dcd13fe"}, + {file = "propcache-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:5fcb98e7598b1ee0addab320d90f65b530297a867dbfe9de52ea838077e16e3d"}, + {file = "propcache-0.5.2-cp310-cp310-win_arm64.whl", hash = "sha256:04dc2390d9edbbaef7461f33322555976ffddf0b650a038649d026358714e6c5"}, + {file = "propcache-0.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74b70780220e2dd89175ca24b81b68b67c83db499ae611e7f2313cb329801c78"}, + {file = "propcache-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a4840ab0ae0216d952f4b53dc6d0b992bfc2bedbfe360bdd9b548bc184c08959"}, + {file = "propcache-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c6844ba6364fb12f403928a82cfd295ab103a2b315c77c747b2dbe4a41894ea7"}, + {file = "propcache-0.5.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2293949b855ce597f2826452d17c2d545fb5622379c4ea6fdf525e9b8e8a2511"}, + {file = "propcache-0.5.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0fd59b5af35f74da48d905dcbad55449ba13be91823cb05a9bd590bbf5b61660"}, + {file = "propcache-0.5.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29f9309a2e42b0d273be006fdb4be2d6c39a47f6f57d8fb1cf9f81481df81b66"}, + {file = "propcache-0.5.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5aaa2b923c1944ac8febd6609cb373540a5563e7cbcb0fd770f75dace2eb817b"}, + {file = "propcache-0.5.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66ea454f095ddf5b6b14f56c064c0941c4788be11e18d2464cf643bf7203ff67"}, + {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:95f1e3f4760d404b13c9976c0229b2b49a3c8e2c62a9ce92efdd2b11ada75e3f"}, + {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:85341b12b9d55bad0bded24cac341bb34289469e03a11f3f583ea1cc1db0326c"}, + {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:26a4dca084132874e639895c3135dfad5eb20bae209f62d1aeb31b03e601c3c0"}, + {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:3b199b9b2b3d6a7edf3183ba8a9a137a22b97f7df525feb5ae1eccf026d2a9c6"}, + {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e59bc9e66329185b93dab73f210f1a37f81cb40f321501db8017c9aea15dba27"}, + {file = "propcache-0.5.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:552ffadf6ad409844bc5919c42a0a83d88314cedddaea0e41e80a8b8fffe881f"}, + {file = "propcache-0.5.2-cp311-cp311-win32.whl", hash = "sha256:cd416c1de191973c52ff1a12a57446bfc7642797b282d7caf2162d7d1b8aa9a0"}, + {file = "propcache-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:44e488ef40dbb452700b2b1f8188934121f6648f52c295055662d2191959ff82"}, + {file = "propcache-0.5.2-cp311-cp311-win_arm64.whl", hash = "sha256:54adaa85a22078d1e306304a40984dc5be99d599bf3dc0a24dc98f7daeab89ab"}, + {file = "propcache-0.5.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:806719138ecd720339a12410fb9614ac9b2b2d3a5fdf8235d56981c36f4039ba"}, + {file = "propcache-0.5.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:db2b80ea58eab4f86b2beec3cc8b39e8ff9276ac20e96b7cce43c8ae84cd6b5a"}, + {file = "propcache-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e5cbfac9f61484f7e9f3597775500cd3ebe8274e9b050c38f9525c77c97520bf"}, + {file = "propcache-0.5.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbc581d2814337da56222fab8dc5f161cd798a434e49bac27930aaef798e144"}, + {file = "propcache-0.5.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:857187f381f88c8e2fa2fe56ab94879d011b883d5a2ee5a1b60a8cd2a06846d9"}, + {file = "propcache-0.5.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:178b4a2cdaac1818e2bf1c5a99b94383fa73ea5382e032a48dec07dc5668dc42"}, + {file = "propcache-0.5.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f328175a2cde1f0ff2c4ed8ce968b9dcfb55f3a7153f39e2957ed994da13476"}, + {file = "propcache-0.5.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5671d09a36b06d0fd4a3da0fccbcae360e9b1570924171a15e9e0997f0249fba"}, + {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80168e2ebe4d3ec6599d10ad8f520304ae1cad9b6c5a95372aef1b66b7bfb53a"}, + {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:45f11346f884bc47444f6e6647131055844134c3175b629f84952e2b5cd62b64"}, + {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8e778ebd44ef4f66ed60a0416b06b489687db264a9c0b3620362f26489492913"}, + {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:c0cb9ed24c8964e172768d455a38254c2dd8a552905729ce006cad3d3dda59b1"}, + {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1d1ad32d9d4355e2be65574fd0bfd3677e7066b009cd5b9b2dee8aa6a6393b33"}, + {file = "propcache-0.5.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c80f4ba3e8f00189165999a742ee526ebeccedf6c3f7beb0c7df821e9772435a"}, + {file = "propcache-0.5.2-cp312-cp312-win32.whl", hash = "sha256:8c7972d8f193740d9175f0998ab38717e6cd322d5935c5b0fef8c0d323fd9031"}, + {file = "propcache-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:d9ee8826a7d47863a08ac44e1a5f611a462eefc3a194b492da242128bec75b42"}, + {file = "propcache-0.5.2-cp312-cp312-win_arm64.whl", hash = "sha256:2800a4a8ead6b28cccd1ec54b59346f0def7922ee1c7598e8499c733cfbb7c84"}, + {file = "propcache-0.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:099aaf4b4d1a02265b92a977edf00b5c4f63b3b17ac6de39b0d637c9cac0188a"}, + {file = "propcache-0.5.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:68ce1c44c7a813a7f71ea04315a8c7b330b63db99d059a797a4651bb6f69f117"}, + {file = "propcache-0.5.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fc299c129490f55f254cd90be0deca4764e36e9a7c08b4aa588479a3bbed3098"}, + {file = "propcache-0.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a6ae2198be502c10f09b2516e7b5d019816924bc3183a43ce792a7bd6625e6f4"}, + {file = "propcache-0.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6041d31504dc1779d700e1edcfb08eea334b357620b06681a4eabb57a74e574e"}, + {file = "propcache-0.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7eabc04151c78a9f4d5bbb5f1faf571e4defeb4b585e0fe95b60ff2dbe4d3d7"}, + {file = "propcache-0.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4db0ba63d693afd40d249bd93f842b5f144f8fcbb83de05660373bcf30517b1d"}, + {file = "propcache-0.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1dbcf7675229b35d31abb6547d8ebc8c27a830ac3f9a794edff6254873ec7c0a"}, + {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d310c013aad2c72f1c3f2f8dd3279d460a858c551f97aeb8c63e4693cca7b4d2"}, + {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:06187263ddad280d05b4d8a8b3bb7d164cbebd469236544a42e6d9b28ac6a4fa"}, + {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3115559b8effafd63b142ea5ed53d63a16ea6469cbc63dce4ee194b42db5d853"}, + {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c60462af8e6dc30c35407c7237ea908d777b22862bbee27bc4699c0d8bcdc45a"}, + {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40314bca9ac559716fe374094fc81c11dcc34b64fd6c585360f5775690505704"}, + {file = "propcache-0.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cfa21e036ce1e1db2be04ba3b85d2df1bb1702fa01932d984c5464c665228ff4"}, + {file = "propcache-0.5.2-cp313-cp313-win32.whl", hash = "sha256:f156a3529f38063b6dbaf356e15602a7f95f8055b1295a438433a6386f10463d"}, + {file = "propcache-0.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:dfed59d0a5aeb01e242e66ff0300bc4a265a7c05f612d30016f0b60b1017d757"}, + {file = "propcache-0.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:ba338430e87ceb9c8f0cf754de38a9860560261e56c00376debd628698a7364f"}, + {file = "propcache-0.5.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a592f5f3da71c8691c788c13cb6734b6d17663d2e1cb8caddf0673d01ef8847d"}, + {file = "propcache-0.5.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6a997d0489e9668a384fcfd5061b857aa5361de73191cac204d04b889cfbbafa"}, + {file = "propcache-0.5.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:10734b5484ea113152ee25a91dccedf81631791805d2c9ccb054958e51842c94"}, + {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cafca7e56c12bb02ae16d283742bef25a61122e9dab2b5b3f2ccbe589ce32164"}, + {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f064f8d2b59177878b7615df1735cd8fe3462ed6be8c7b217d17a276489c2b7f"}, + {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f78abfa8dfc32376fd1aacf597b2f2fbbe0ea751419aee718af5d4f82537ef8c"}, + {file = "propcache-0.5.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7467da8a9822bf1a55336f877340c5bcbd3c482afc43a99771169f74a26dedc"}, + {file = "propcache-0.5.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a6ddc6ac9e25de626c1f129c1b467d7ecd33ce2237d3fd0c4e429feef0a7ee1f"}, + {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2f22cbbac9e26a8e864c0985ff1268d5d939d53d9d9411a9824279097e03a2cb"}, + {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:fc76378c62a0f04d0cd82fbb1a2cd2d7e28fcb40d5873f28a6c44e388aaa2751"}, + {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:acd2c8edba48e31e58a363b8cf4e5c7db3b04b3f9e371f601df30d9b0d244836"}, + {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:452b5065457eb9991ec5eb38ff41d6cd4c991c9ac7c531c4d5849ae473a9a13f"}, + {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:3430bb2bfe1331885c427745a751e774ee679fd4344f80b97bf879815fe8fa55"}, + {file = "propcache-0.5.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cef6cea3922890dd6c9654971001fa797b526c16ab5e1e46c05fd6f877be7568"}, + {file = "propcache-0.5.2-cp313-cp313t-win32.whl", hash = "sha256:72d61e16dd78228b58c5d47be830ff3da7e5f139abdf0aef9d86cde1c5cf2191"}, + {file = "propcache-0.5.2-cp313-cp313t-win_amd64.whl", hash = "sha256:0958834041a0166d343b8d2cedcd8bcbaeb4fdbe0cf08320c5379f143c3be6e7"}, + {file = "propcache-0.5.2-cp313-cp313t-win_arm64.whl", hash = "sha256:6de8bd93ddde9b992cf2b2e0d796d501a19026b5b9fd87356d7d0779531a8d96"}, + {file = "propcache-0.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:46088abff4cba581dea21ae0467a480526cb25aa5f3c269e909f800328bc3999"}, + {file = "propcache-0.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fc88b26f08d634f7bc819a7852e5214f5802641ab8d9fd5326892292eee1993e"}, + {file = "propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539"}, + {file = "propcache-0.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba57fffe4ac99c5d30076161b5866336d97600769bad35cc68f7774b15298a4e"}, + {file = "propcache-0.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:583c19759d9eec1e5b69e2fbef36a7d9c326041be9746cb822d335c8cedc2979"}, + {file = "propcache-0.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d0326e2e5e1f3163fa306c834e48e8d490e5fae607a097a40c0648109b47ba80"}, + {file = "propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825"}, + {file = "propcache-0.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c66afea89b1e43725731d2004732a046fe6fe955d51f952c3e95a7314a284a39"}, + {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc37dec6c6cdad0b57881a5658fd14fbf53e333b1a86cf86559f190e1d9ec4"}, + {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5570dbcc97571c15f68068e529c92715a12f8d54030e272d264b377e22bd17a5"}, + {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f814362777a9f841adddb200ecdf8f5cb1e5a3c4b7a86378edbd6ccb26edd702"}, + {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:196913dea116aeb5a2ba95af4ddcb7ea85559ae07d8eee8751688310d09168c3"}, + {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6e7b8719005dd1175be4ab1cd25e9b98659a5e0347331506ec6760d2773a7fb5"}, + {file = "propcache-0.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:51f96d685ab16e88cab128cd37a52c5da540809c8b879fa047731bfcb4ad35a4"}, + {file = "propcache-0.5.2-cp314-cp314-win32.whl", hash = "sha256:cc6fc3cc62e8501d3ed62894425040d2728ecddb1ed072737a5c70bd537aa9f0"}, + {file = "propcache-0.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c"}, + {file = "propcache-0.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:0d2c9bf8528f135dbb805ce027567e09164f7efa51a2be07458a2c0420f292d0"}, + {file = "propcache-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4bc8ff1feffc6a61c7002ffe84634c41b822e104990ae009f44a0834430070bb"}, + {file = "propcache-0.5.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:79aa3ff0a9b566633b642fa9caf7e21ed1c13d6feca718187873f199e1514078"}, + {file = "propcache-0.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1b31822f4474c4036bae62de9402710051d431a606d6a0f907fec79935a071aa"}, + {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fef48778b5a2a756523fdb781326b028ca75e32858b04f2cdd19f394564917"}, + {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8b73ab70f1a3351fbc71f663b3e645af6dd0329100c353081cf69c37433fc6fe"}, + {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5538d2c13d93e4698af7e092b57bc7298fd35d1d58e656ae18f23ee0d0378e03"}, + {file = "propcache-0.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd645f03898405cabe694fb8bc35241e3a9c332ec85627584fe3de201452b335"}, + {file = "propcache-0.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a473b3440261e0c60706e732b2ed2f517857344fc21bf48fdfe211e2d98eb285"}, + {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7afa37062e6650640e932e4cc9297d81f9f42d9944029cc386b8247dea4da837"}, + {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8a90efd5777e996e42d568db9ac740b944d691e565cbfd31b2f7832f9184b2b8"}, + {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f19bb891234d72535764d703bfed1153cc34f4214d5bd7150aee1eec9e8f4366"}, + {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:32775082acd2d807ee3db715c7770d38767b817870acfa08c29e057f3c4d5b56"}, + {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9282fb1a3bccd038da9f768b927b24a0c753e466c086b7c4f3c6982851eefb2d"}, + {file = "propcache-0.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc49723e2f60d6b32a0f0b08a3fd6d13203c07f1cd9566cfce0f12a917c967a2"}, + {file = "propcache-0.5.2-cp314-cp314t-win32.whl", hash = "sha256:2d7aa89ebca5acc98cba9d1472d976e394782f587bad6661003602a619fd1821"}, + {file = "propcache-0.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d447bb0b3054be5818458fbb171208b1d9ff11eba14e18ca18b90cbb45767370"}, + {file = "propcache-0.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:fe67a3d11cd9b4efabfa45c3d00ffba2b26811442a73a581a94b67c2b5faccf6"}, + {file = "propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe"}, + {file = "propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427"}, ] [[package]] name = "proto-plus" -version = "1.27.2" +version = "1.28.2" description = "Beautiful, Pythonic protocol buffers" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "proto_plus-1.27.2-py3-none-any.whl", hash = "sha256:6432f75893d3b9e70b9c412f1d2f03f65b11fb164b793d14ae2ca01821d22718"}, - {file = "proto_plus-1.27.2.tar.gz", hash = "sha256:b2adde53adadf75737c44d3dcb0104fde65250dfc83ad59168b4aa3e574b6a24"}, + {file = "proto_plus-1.28.2-py3-none-any.whl", hash = "sha256:b874236fcac2358f601e4330bcb76cb8b89c851303ccf4078408b3d4774d1c52"}, + {file = "proto_plus-1.28.2.tar.gz", hash = "sha256:26d843eb99c1e32fdf1d20ff0faae56607f7748fe774acf9ecd5cfe6c6472501"}, ] [package.dependencies] @@ -4813,23 +4588,20 @@ testing = ["google-api-core (>=1.31.5)"] [[package]] name = "protobuf" -version = "5.29.6" +version = "7.35.1" description = "" optional = false -python-versions = ">=3.8" +python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "protobuf-5.29.6-cp310-abi3-win32.whl", hash = "sha256:62e8a3114992c7c647bce37dcc93647575fc52d50e48de30c6fcb28a6a291eb1"}, - {file = "protobuf-5.29.6-cp310-abi3-win_amd64.whl", hash = "sha256:7e6ad413275be172f67fdee0f43484b6de5a904cc1c3ea9804cb6fe2ff366eda"}, - {file = "protobuf-5.29.6-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:b5a169e664b4057183a34bdc424540e86eea47560f3c123a0d64de4e137f9269"}, - {file = "protobuf-5.29.6-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:a8866b2cff111f0f863c1b3b9e7572dc7eaea23a7fae27f6fc613304046483e6"}, - {file = "protobuf-5.29.6-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:e3387f44798ac1106af0233c04fb8abf543772ff241169946f698b3a9a3d3ab9"}, - {file = "protobuf-5.29.6-cp38-cp38-win32.whl", hash = "sha256:36ade6ff88212e91aef4e687a971a11d7d24d6948a66751abc1b3238648f5d05"}, - {file = "protobuf-5.29.6-cp38-cp38-win_amd64.whl", hash = "sha256:831e2da16b6cc9d8f1654c041dd594eda43391affd3c03a91bea7f7f6da106d6"}, - {file = "protobuf-5.29.6-cp39-cp39-win32.whl", hash = "sha256:cb4c86de9cd8a7f3a256b9744220d87b847371c6b2f10bde87768918ef33ba49"}, - {file = "protobuf-5.29.6-cp39-cp39-win_amd64.whl", hash = "sha256:76e07e6567f8baf827137e8d5b8204b6c7b6488bbbff1bf0a72b383f77999c18"}, - {file = "protobuf-5.29.6-py3-none-any.whl", hash = "sha256:6b9edb641441b2da9fa8f428760fc136a49cf97a52076010cf22a2ff73438a86"}, - {file = "protobuf-5.29.6.tar.gz", hash = "sha256:da9ee6a5424b6b30fd5e45c5ea663aef540ca95f9ad99d1e887e819cdf9b8723"}, + {file = "protobuf-7.35.1-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:24f857477359a85c0c235261b8ba905fd51b2562f4a64ca1df5473f29850cbf6"}, + {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:11d6b0ec246892d85215b0a13ca6e0233cf5284b68f0ac02646427f4ff88a799"}, + {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:b73f9489a4b8b1c9cb1f8ed951c736392592edb24b9d6819f36d2e10b171d5b4"}, + {file = "protobuf-7.35.1-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:74758715c53d7158fb76caf4f0cfdacc5329a4b1bb994f865d6cf302d413a1c4"}, + {file = "protobuf-7.35.1-cp310-abi3-win32.whl", hash = "sha256:353652e4efd0bca5b5fc2656abf8307ef351f0cf938c9eba09f0e09c20a25c30"}, + {file = "protobuf-7.35.1-cp310-abi3-win_amd64.whl", hash = "sha256:230a75ddfc2de4806e56696ce9640c1cdfdb6543b7cfce98d42a4c0a0e7bdb87"}, + {file = "protobuf-7.35.1-py3-none-any.whl", hash = "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9"}, + {file = "protobuf-7.35.1.tar.gz", hash = "sha256:ce115a26fe0c39a2c29973d914d327e516a6455464489fe3cd1e51a1b354f81a"}, ] [[package]] @@ -4925,14 +4697,14 @@ files = [ [[package]] name = "pyasn1" -version = "0.6.3" +version = "0.6.4" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" optional = false python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "pyasn1-0.6.3-py3-none-any.whl", hash = "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde"}, - {file = "pyasn1-0.6.3.tar.gz", hash = "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf"}, + {file = "pyasn1-0.6.4-py3-none-any.whl", hash = "sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b"}, + {file = "pyasn1-0.6.4.tar.gz", hash = "sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81"}, ] [[package]] @@ -5172,12 +4944,11 @@ version = "2.20.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.9" -groups = ["main", "dev"] +groups = ["dev"] files = [ {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, ] -markers = {main = "python_version < \"3.14\""} [package.extras] windows-terminal = ["colorama (>=0.4.6)"] @@ -5316,46 +5087,46 @@ image = ["Pillow (>=8.0.0)"] [[package]] name = "pypdfium2" -version = "5.7.1" +version = "5.12.1" description = "Python bindings to PDFium" optional = false python-versions = ">=3.6" groups = ["main"] files = [ - {file = "pypdfium2-5.7.1-py3-none-android_23_arm64_v8a.whl", hash = "sha256:8008f45e8adc4fc1ec2a51e018e01cd0692d4859bdbb28e88be221804f329468"}, - {file = "pypdfium2-5.7.1-py3-none-android_23_armeabi_v7a.whl", hash = "sha256:892fcb5a618f5f551fffdb968ac2d64911953c3ba0f9aa628239705af68dbe15"}, - {file = "pypdfium2-5.7.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7431847d45dedc3c7ffede15b58ac611e996a0cdcd61318a0190d46b9980ac2b"}, - {file = "pypdfium2-5.7.1-py3-none-macosx_11_0_x86_64.whl", hash = "sha256:548bd09c9f97565ae8ddba30bb65823cbf791b84e4cdb63ed582aec2c289dbe2"}, - {file = "pypdfium2-5.7.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18a15ad0918acc3ea98778394f0331b9ad2a1b7384ab3d8d8c63422ffd01ed13"}, - {file = "pypdfium2-5.7.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1df04564659d807fb38810d9bd1ac18419d8acbb5f87f2cb20675d7332635b18"}, - {file = "pypdfium2-5.7.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a146d036a6b085a406aa256548b827b63016714fd77f8e11b7f704c1175e8cc"}, - {file = "pypdfium2-5.7.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3397b0d705b6858c87dec1dc9c44d4c7094601a9b231097f441b64d1a7d5ff0b"}, - {file = "pypdfium2-5.7.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc2cdf603ac766b91b7c1b455197ec1c3471089d75f999b046edb65ed6cedd80"}, - {file = "pypdfium2-5.7.1-py3-none-manylinux_2_27_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1b1a6a5f3320b59138e7570a3f78840540383d058ac180a9a21f924ad3bd7f83"}, - {file = "pypdfium2-5.7.1-py3-none-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:91b809c40a5fc248107d13fbcf1dd2c64dbc8e572693a9b93e350bf31efda92b"}, - {file = "pypdfium2-5.7.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:85611ef61cbc0f5e04de8f99fec0f3db3920b09f46c62afa08c9caa21a74b353"}, - {file = "pypdfium2-5.7.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b2764ab909f9b444d4e643be90b064c4053e6828c28bfd47639fc84526ba244d"}, - {file = "pypdfium2-5.7.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:fcea3cc20b7cca7d84ceee68b9c6ef7fe773fb71c145542769dc2ceb27e9698a"}, - {file = "pypdfium2-5.7.1-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:f04546bc314973397148805d44f8e660e81aa80c2a87e12afb892c11493ded6c"}, - {file = "pypdfium2-5.7.1-py3-none-musllinux_1_2_riscv64.whl", hash = "sha256:66275c8a854969bdf905abc7599e5623d62739c44604d69788ff5457082d275b"}, - {file = "pypdfium2-5.7.1-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:bbed8f32040ce3b3236a512265976017c2465ea6643a1730f008b39e0339b8ce"}, - {file = "pypdfium2-5.7.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:c55d3df09bd0d72a1d192107dcbf80bcb2791662a3eca3b084001f947d3040d5"}, - {file = "pypdfium2-5.7.1-py3-none-win32.whl", hash = "sha256:4f6bbe1211c5883c8fc9ce11008347e5b96ec6571456d959ae289cecdb2867f0"}, - {file = "pypdfium2-5.7.1-py3-none-win_amd64.whl", hash = "sha256:fdf117af26bd310f4f176b3cf0e2e23f0f800e48dcf2bcf6c2cca0de3326f5cb"}, - {file = "pypdfium2-5.7.1-py3-none-win_arm64.whl", hash = "sha256:622821698fcc30fc560bd4eead6df9e6b846de9876b82861bed0091c09a4c27b"}, - {file = "pypdfium2-5.7.1.tar.gz", hash = "sha256:3b3b20a56048dbe3fd4bf397f9bec854c834668bc47ef6a7d9041b23bb04317b"}, + {file = "pypdfium2-5.12.1-py3-none-android_23_arm64_v8a.whl", hash = "sha256:05bab9b1ba2de7fc299ae2af25cb9c8a0543bc8bb893e879fe8c9ba8310e9ce4"}, + {file = "pypdfium2-5.12.1-py3-none-android_23_armeabi_v7a.whl", hash = "sha256:d4ee061e566a6422b660cdddaaa799a2d1cbf2f016921bcaf24d61426d01d942"}, + {file = "pypdfium2-5.12.1-py3-none-macosx_13_0_arm64.whl", hash = "sha256:66a9ed40d70a5d728cd42148fecb9d7a0917c6161d6bb67c844093a4ed1df089"}, + {file = "pypdfium2-5.12.1-py3-none-macosx_13_0_x86_64.whl", hash = "sha256:847378a5ab41332998b2621b21bab2e96dc8c3eff36a08bce26695b964163983"}, + {file = "pypdfium2-5.12.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6eabf028ad8e7bc7811c9acf3a72718c180569b624b844d2c6cc974609784275"}, + {file = "pypdfium2-5.12.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7857cfa6642ec5a09db12ff8f5cf6b6494585b5e3a605399fddc4fb862837b63"}, + {file = "pypdfium2-5.12.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05bfa20a08a96584253bbe38b60e13f81a037eac31c5579e607ec1480ad25dbf"}, + {file = "pypdfium2-5.12.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f059f7bdbdf4352eb83691071096940d769d6ae5930b8734237fdb1bd78fbc2"}, + {file = "pypdfium2-5.12.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e10cbf41b21233ec5e20adfc170cf60edd77abead86a97dc708fff55a8a886c7"}, + {file = "pypdfium2-5.12.1-py3-none-manylinux_2_27_s390x.manylinux_2_28_s390x.whl", hash = "sha256:07eeebb2784f4cd38d386b924235df43217a397442796673296bb6efbdaad1d0"}, + {file = "pypdfium2-5.12.1-py3-none-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5c3e6cbe43581af79526184643920ab03a9401a0c79f2226bea9d4d1e3d34008"}, + {file = "pypdfium2-5.12.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4648f0905441bcb141687ca2263bbf38a1aa056b943eef06019f91cff3e1da4a"}, + {file = "pypdfium2-5.12.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:bdff622181fab64f32328591c9c8287cdc745c9a1f2afc26ca3feba39e3e6645"}, + {file = "pypdfium2-5.12.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:236dbdc88aa54f14b27937ccb2ebe3dcf08c10dbb8652f432ea982dc9af39732"}, + {file = "pypdfium2-5.12.1-py3-none-musllinux_1_2_ppc64le.whl", hash = "sha256:9c8856ce7dd77a7827476c7d75afe1197d6cd505f5cb4167b6aacf661f3f8ea5"}, + {file = "pypdfium2-5.12.1-py3-none-musllinux_1_2_riscv64.whl", hash = "sha256:5f257bb40fa44ce9ba18d2c919777dbd3f16bf22548b1d68fd56c7c92f1de530"}, + {file = "pypdfium2-5.12.1-py3-none-musllinux_1_2_s390x.whl", hash = "sha256:974082344172da76a5c3c0782eaedfe6069dbe88db77d8c671ef36b61e9b14e2"}, + {file = "pypdfium2-5.12.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:715ae16b34ea1d64884d58800155179ba700e9ea65a2f583b020666acd2bfb12"}, + {file = "pypdfium2-5.12.1-py3-none-win32.whl", hash = "sha256:e5358d2ce4ebc5c899aab1df9ca5d215357244e9168aa443225d3c1e649c7eac"}, + {file = "pypdfium2-5.12.1-py3-none-win_amd64.whl", hash = "sha256:9609be73a6701a68f29dffe0335f7a2e4b3ba581542ed65d35d49f761a4600ca"}, + {file = "pypdfium2-5.12.1-py3-none-win_arm64.whl", hash = "sha256:afc0b7e0c975a429abc75875209ce17b66d749f6ac5cbe8ba72470e83901e304"}, + {file = "pypdfium2-5.12.1.tar.gz", hash = "sha256:d0e0648fb2e28f50efcd1ec0a5a18ced9f4d66b2c227fae9b603f0a883b2d13f"}, ] [[package]] name = "pyproject-api" -version = "1.10.1" +version = "1.11.0" description = "API to interact with the python pyproject.toml based projects" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pyproject_api-1.10.1-py3-none-any.whl", hash = "sha256:fa9e6f66c35b5017e909825d8f2b5d5482ea699d7be809d21c03bd1f7317f36a"}, - {file = "pyproject_api-1.10.1.tar.gz", hash = "sha256:c2b2726bd7aa9217b6c50b621fef5b2ae5def4d55b779c9e0694c15e0a8517ba"}, + {file = "pyproject_api-1.11.0-py3-none-any.whl", hash = "sha256:860060c8832dce983b5eec6f41c4c43eb3ec06ff7332387a63acdf5ca27b68d8"}, + {file = "pyproject_api-1.11.0.tar.gz", hash = "sha256:b8807d85a293e6c9f133e6575946fed45f1d42b22d58c780b33aa2421a799549"}, ] [package.dependencies] @@ -5376,14 +5147,14 @@ files = [ [[package]] name = "pytest" -version = "9.0.3" +version = "9.1.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}, - {file = "pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}, + {file = "pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c"}, + {file = "pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313"}, ] [package.dependencies] @@ -5444,24 +5215,20 @@ six = ">=1.5" [[package]] name = "python-discovery" -version = "1.4.2" +version = "1.5.0" description = "Python interpreter discovery" optional = false python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "python_discovery-1.4.2-py3-none-any.whl", hash = "sha256:475803f53b7b2ed6e490e27373f9d8340f7d2eebf9acdaf645d7d714c97bb500"}, - {file = "python_discovery-1.4.2.tar.gz", hash = "sha256:8f3746c4b4968d22afbb97d36e1a0e5b66e6c0f297290f2e95f05b9b8bf18690"}, + {file = "python_discovery-1.5.0-py3-none-any.whl", hash = "sha256:70c4fc61b4e7404e44f01d6fc44a715c4d685ca6cea83d295922f05891877c98"}, + {file = "python_discovery-1.5.0.tar.gz", hash = "sha256:3e014c6327154d3dda27939a9a0dc9c5c000439f1906d3f303b48f984bd2ecef"}, ] [package.dependencies] filelock = ">=3.15.4" platformdirs = ">=4.3.6,<5" -[package.extras] -docs = ["furo (>=2025.12.19)", "sphinx (>=9.1)", "sphinx-autodoc-typehints (>=3.6.3)", "sphinxcontrib-mermaid (>=2)", "sphinxcontrib-towncrier (>=0.4)", "towncrier (>=25.8)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.5.4)", "pytest (>=8.3.5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] - [[package]] name = "python-docx" version = "1.2.0" @@ -5592,45 +5359,46 @@ dev = ["black", "build", "mypy", "pytest", "pytest-cov", "setuptools", "tox", "t [[package]] name = "pytz" -version = "2026.2" +version = "2026.3.post1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" groups = ["main"] files = [ - {file = "pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126"}, - {file = "pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a"}, + {file = "pytz-2026.3.post1-py2.py3-none-any.whl", hash = "sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815"}, + {file = "pytz-2026.3.post1.tar.gz", hash = "sha256:2211d3fcf9a797d3405cac96ac7f61d80e6a644f72a3309607282fe8a2010c5d"}, ] [[package]] name = "pywin32" -version = "311" -description = "Python for Window Extensions" +version = "312" +description = "Python for Windows Extensions" optional = false -python-versions = "*" +python-versions = ">=3.9" groups = ["main"] markers = "sys_platform == \"win32\" or platform_system == \"Windows\"" files = [ - {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, - {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, - {file = "pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b"}, - {file = "pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151"}, - {file = "pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503"}, - {file = "pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2"}, - {file = "pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31"}, - {file = "pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067"}, - {file = "pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852"}, - {file = "pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d"}, - {file = "pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d"}, - {file = "pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a"}, - {file = "pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee"}, - {file = "pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87"}, - {file = "pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42"}, - {file = "pywin32-311-cp38-cp38-win32.whl", hash = "sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c"}, - {file = "pywin32-311-cp38-cp38-win_amd64.whl", hash = "sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd"}, - {file = "pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b"}, - {file = "pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91"}, - {file = "pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d"}, + {file = "pywin32-312-cp310-cp310-win32.whl", hash = "sha256:772235332b5d1024c696f11cea1ae4be7930f0a8b894bb43db14e3f435f1ff7e"}, + {file = "pywin32-312-cp310-cp310-win_amd64.whl", hash = "sha256:5dbc35d2b5320dc07f25fa31269cfb767471002b17de5eb067d03da68c7cb2db"}, + {file = "pywin32-312-cp310-cp310-win_arm64.whl", hash = "sha256:3020656e34f1cf7faeb7bccd2b84653a607c6ff0c55ada85e6487d61716deabd"}, + {file = "pywin32-312-cp311-cp311-win32.whl", hash = "sha256:17948aeadbdb091f0ced6ef0841620794e68327b94ee415571c1203594b7215c"}, + {file = "pywin32-312-cp311-cp311-win_amd64.whl", hash = "sha256:d11417d84412f859b722fad0841b3614459ed0047f7542d8362e77884f6b6e8a"}, + {file = "pywin32-312-cp311-cp311-win_arm64.whl", hash = "sha256:b2200a054ca6d6625c4842fc56a4976a4b47f96b73dbe5538c3f813a80359f47"}, + {file = "pywin32-312-cp312-cp312-win32.whl", hash = "sha256:dab4f65ac9c4e48400a2a0530c46c3c579cd5905ecd11b80692373915269208b"}, + {file = "pywin32-312-cp312-cp312-win_amd64.whl", hash = "sha256:b457f6d628a47e8a7346ce22acb7e1a46a4a78b52e1d17e1af56871bd19a93bc"}, + {file = "pywin32-312-cp312-cp312-win_arm64.whl", hash = "sha256:6017c58e12f6809fbb0555b75df144c2922a9ffd18e4b9b5afa863b6c1a9d950"}, + {file = "pywin32-312-cp313-cp313-win32.whl", hash = "sha256:7a27df850933d16a8eabfbaeb73d52b273e2da667f80d70b01a89d1f6828d02c"}, + {file = "pywin32-312-cp313-cp313-win_amd64.whl", hash = "sha256:c53e878d15a1c44788082bfe712a905433473aa38f86375b7cf8b45e3acbaaf9"}, + {file = "pywin32-312-cp313-cp313-win_arm64.whl", hash = "sha256:59aba5d5940842075343a5ddc6b11f1cdf0d1567fe745290359dfbcc7c2eb831"}, + {file = "pywin32-312-cp314-cp314-win32.whl", hash = "sha256:a77a90fbb6881238d2ca9c6fd797b25817f3768fe78d214a90137ff055a75f5b"}, + {file = "pywin32-312-cp314-cp314-win_amd64.whl", hash = "sha256:a4dd3a848290ef724347b19f301045831d8e802fa4464f491b98b1e0a081432e"}, + {file = "pywin32-312-cp314-cp314-win_arm64.whl", hash = "sha256:9fce94568364e0155e6dfb781ac5d95903be8baf28670632beab1b523f300daa"}, + {file = "pywin32-312-cp315-cp315-win32.whl", hash = "sha256:5c1fbe4a937a73ae9297384a3da38518cbc694c68ad8a809b2e19acd350f03ed"}, + {file = "pywin32-312-cp315-cp315-win_amd64.whl", hash = "sha256:c2f03a0f73f804a13c2735b99392b0cd426bb4f2c4d0178e5ac966a0f21618d5"}, + {file = "pywin32-312-cp315-cp315-win_arm64.whl", hash = "sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9"}, + {file = "pywin32-312-cp39-cp39-win32.whl", hash = "sha256:d620900033cc7531e50727c3c8333091df5dd3ffe6d68cdca38c03f5821408d5"}, + {file = "pywin32-312-cp39-cp39-win_amd64.whl", hash = "sha256:dc90147579a905b8635e1b0ec6514967dcb07e6e0d9c42f1477feef14cac23bb"}, + {file = "pywin32-312-cp39-cp39-win_arm64.whl", hash = "sha256:02ebca0f0242b75292e218065004310d6a477407c09fa449bfe4f6022bc0c0fc"}, ] [[package]] @@ -5814,20 +5582,20 @@ all = ["numpy"] [[package]] name = "redis" -version = "7.4.0" +version = "8.0.1" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "redis-7.4.0-py3-none-any.whl", hash = "sha256:a9c74a5c893a5ef8455a5adb793a31bb70feb821c86eccb62eebef5a19c429ec"}, - {file = "redis-7.4.0.tar.gz", hash = "sha256:64a6ea7bf567ad43c964d2c30d82853f8df927c5c9017766c55a1d1ed95d18ad"}, + {file = "redis-8.0.1-py3-none-any.whl", hash = "sha256:47daa35a058c23468d6437f17a8c76882cb316b838ef763036af99b96cedd743"}, + {file = "redis-8.0.1.tar.gz", hash = "sha256:afc5a7a2f5a084f5b1880dec548dd45be17db7e43c82a30d84f952aefb05cfb0"}, ] [package.extras] circuit-breaker = ["pybreaker (>=1.4.0)"] hiredis = ["hiredis (>=3.2.0)"] -jwt = ["pyjwt (>=2.9.0)"] +jwt = ["pyjwt (>=2.13.0)"] ocsp = ["cryptography (>=36.0.1)", "pyopenssl (>=20.0.1)", "requests (>=2.31.0)"] otel = ["opentelemetry-api (>=1.39.1)", "opentelemetry-exporter-otlp-proto-http (>=1.39.1)", "opentelemetry-sdk (>=1.39.1)"] xxhash = ["xxhash (>=3.6.0,<3.7.0)"] @@ -5851,127 +5619,127 @@ typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "regex" -version = "2026.4.4" +version = "2026.7.19" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.10" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "regex-2026.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:74fa82dcc8143386c7c0392e18032009d1db715c25f4ba22d23dc2e04d02a20f"}, - {file = "regex-2026.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a85b620a388d6c9caa12189233109e236b3da3deffe4ff11b84ae84e218a274f"}, - {file = "regex-2026.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2895506ebe32cc63eeed8f80e6eae453171cfccccab35b70dc3129abec35a5b8"}, - {file = "regex-2026.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6780f008ee81381c737634e75c24e5a6569cc883c4f8e37a37917ee79efcafd9"}, - {file = "regex-2026.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:88e9b048345c613f253bea4645b2fe7e579782b82cac99b1daad81e29cc2ed8e"}, - {file = "regex-2026.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:be061028481186ba62a0f4c5f1cc1e3d5ab8bce70c89236ebe01023883bc903b"}, - {file = "regex-2026.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d2228c02b368d69b724c36e96d3d1da721561fb9cc7faa373d7bf65e07d75cb5"}, - {file = "regex-2026.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0540e5b733618a2f84e9cb3e812c8afa82e151ca8e19cf6c4e95c5a65198236f"}, - {file = "regex-2026.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cf9b1b2e692d4877880388934ac746c99552ce6bf40792a767fd42c8c99f136d"}, - {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:011bb48bffc1b46553ac704c975b3348717f4e4aa7a67522b51906f99da1820c"}, - {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8512fcdb43f1bf18582698a478b5ab73f9c1667a5b7548761329ef410cd0a760"}, - {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:867bddc63109a0276f5a31999e4c8e0eb7bbbad7d6166e28d969a2c1afeb97f9"}, - {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1b9a00b83f3a40e09859c78920571dcb83293c8004079653dd22ec14bbfa98c7"}, - {file = "regex-2026.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e355be718caf838aa089870259cf1776dc2a4aa980514af9d02c59544d9a8b22"}, - {file = "regex-2026.4.4-cp310-cp310-win32.whl", hash = "sha256:33bfda9684646d323414df7abe5692c61d297dbb0530b28ec66442e768813c59"}, - {file = "regex-2026.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:0709f22a56798457ae317bcce42aacee33c680068a8f14097430d9f9ba364bee"}, - {file = "regex-2026.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:ee9627de8587c1a22201cb16d0296ab92b4df5cdcb5349f4e9744d61db7c7c98"}, - {file = "regex-2026.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4c36a85b00fadb85db9d9e90144af0a980e1a3d2ef9cd0f8a5bef88054657c6"}, - {file = "regex-2026.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dcb5453ecf9cd58b562967badd1edbf092b0588a3af9e32ee3d05c985077ce87"}, - {file = "regex-2026.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6aa809ed4dc3706cc38594d67e641601bd2f36d5555b2780ff074edfcb136cf8"}, - {file = "regex-2026.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33424f5188a7db12958246a54f59a435b6cb62c5cf9c8d71f7cc49475a5fdada"}, - {file = "regex-2026.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d346fccdde28abba117cc9edc696b9518c3307fbfcb689e549d9b5979018c6d"}, - {file = "regex-2026.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:415a994b536440f5011aa77e50a4274d15da3245e876e5c7f19da349caaedd87"}, - {file = "regex-2026.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21e5eb86179b4c67b5759d452ea7c48eb135cd93308e7a260aa489ed2eb423a4"}, - {file = "regex-2026.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:312ec9dd1ae7d96abd8c5a36a552b2139931914407d26fba723f9e53c8186f86"}, - {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0d2b28aa1354c7cd7f71b7658c4326f7facac106edd7f40eda984424229fd59"}, - {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:349d7310eddff40429a099c08d995c6d4a4bfaf3ff40bd3b5e5cb5a5a3c7d453"}, - {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e7ab63e9fe45a9ec3417509e18116b367e89c9ceb6219222a3396fa30b147f80"}, - {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fe896e07a5a2462308297e515c0054e9ec2dd18dfdc9427b19900b37dfe6f40b"}, - {file = "regex-2026.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eb59c65069498dbae3c0ef07bbe224e1eaa079825a437fb47a479f0af11f774f"}, - {file = "regex-2026.4.4-cp311-cp311-win32.whl", hash = "sha256:2a5d273181b560ef8397c8825f2b9d57013de744da9e8257b8467e5da8599351"}, - {file = "regex-2026.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:9542ccc1e689e752594309444081582f7be2fdb2df75acafea8a075108566735"}, - {file = "regex-2026.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:b5f9fb784824a042be3455b53d0b112655686fdb7a91f88f095f3fee1e2a2a54"}, - {file = "regex-2026.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c07ab8794fa929e58d97a0e1796b8b76f70943fa39df225ac9964615cf1f9d52"}, - {file = "regex-2026.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c785939dc023a1ce4ec09599c032cc9933d258a998d16ca6f2b596c010940eb"}, - {file = "regex-2026.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b1ce5c81c9114f1ce2f9288a51a8fd3aeea33a0cc440c415bf02da323aa0a76"}, - {file = "regex-2026.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:760ef21c17d8e6a4fe8cf406a97cf2806a4df93416ccc82fc98d25b1c20425be"}, - {file = "regex-2026.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7088fcdcb604a4417c208e2169715800d28838fefd7455fbe40416231d1d47c1"}, - {file = "regex-2026.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:07edca1ba687998968f7db5bc355288d0c6505caa7374f013d27356d93976d13"}, - {file = "regex-2026.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f657a7c1c6ec51b5e0ba97c9817d06b84ea5fa8d82e43b9405de0defdc2b9"}, - {file = "regex-2026.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2b69102a743e7569ebee67e634a69c4cb7e59d6fa2e1aa7d3bdbf3f61435f62d"}, - {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dac006c8b6dda72d86ea3d1333d45147de79a3a3f26f10c1cf9287ca4ca0ac3"}, - {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50a766ee2010d504554bfb5f578ed2e066898aa26411d57e6296230627cdefa0"}, - {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9e2f5217648f68e3028c823df58663587c1507a5ba8419f4fdfc8a461be76043"}, - {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39d8de85a08e32632974151ba59c6e9140646dcc36c80423962b1c5c0a92e244"}, - {file = "regex-2026.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55d9304e0e7178dfb1e106c33edf834097ddf4a890e2f676f6c5118f84390f73"}, - {file = "regex-2026.4.4-cp312-cp312-win32.whl", hash = "sha256:04bb679bc0bde8a7bfb71e991493d47314e7b98380b083df2447cda4b6edb60f"}, - {file = "regex-2026.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:db0ac18435a40a2543dbb3d21e161a6c78e33e8159bd2e009343d224bb03bb1b"}, - {file = "regex-2026.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:4ce255cc05c1947a12989c6db801c96461947adb7a59990f1360b5983fab4983"}, - {file = "regex-2026.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:62f5519042c101762509b1d717b45a69c0139d60414b3c604b81328c01bd1943"}, - {file = "regex-2026.4.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3790ba9fb5dd76715a7afe34dbe603ba03f8820764b1dc929dd08106214ed031"}, - {file = "regex-2026.4.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fae3c6e795d7678963f2170152b0d892cf6aee9ee8afc8c45e6be38d5107fe7"}, - {file = "regex-2026.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:298c3ec2d53225b3bf91142eb9691025bab610e0c0c51592dde149db679b3d17"}, - {file = "regex-2026.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e9638791082eaf5b3ac112c587518ee78e083a11c4b28012d8fe2a0f536dfb17"}, - {file = "regex-2026.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae3e764bd4c5ff55035dc82a8d49acceb42a5298edf6eb2fc4d328ee5dd7afae"}, - {file = "regex-2026.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ffa81f81b80047ba89a3c69ae6a0f78d06f4a42ce5126b0eb2a0a10ad44e0b2e"}, - {file = "regex-2026.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f56ebf9d70305307a707911b88469213630aba821e77de7d603f9d2f0730687d"}, - {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:773d1dfd652bbffb09336abf890bfd64785c7463716bf766d0eb3bc19c8b7f27"}, - {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d51d20befd5275d092cdffba57ded05f3c436317ee56466c8928ac32d960edaf"}, - {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:0a51cdb3c1e9161154f976cb2bef9894bc063ac82f31b733087ffb8e880137d0"}, - {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ae5266a82596114e41fb5302140e9630204c1b5f325c770bec654b95dd54b0aa"}, - {file = "regex-2026.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c882cd92ec68585e9c1cf36c447ec846c0d94edd706fe59e0c198e65822fd23b"}, - {file = "regex-2026.4.4-cp313-cp313-win32.whl", hash = "sha256:05568c4fbf3cb4fa9e28e3af198c40d3237cf6041608a9022285fe567ec3ad62"}, - {file = "regex-2026.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:3384df51ed52db0bea967e21458ab0a414f67cdddfd94401688274e55147bb81"}, - {file = "regex-2026.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:acd38177bd2c8e69a411d6521760806042e244d0ef94e2dd03ecdaa8a3c99427"}, - {file = "regex-2026.4.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f94a11a9d05afcfcfa640e096319720a19cc0c9f7768e1a61fceee6a3afc6c7c"}, - {file = "regex-2026.4.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:36bcb9d6d1307ab629edc553775baada2aefa5c50ccc0215fbfd2afcfff43141"}, - {file = "regex-2026.4.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:261c015b3e2ed0919157046d768774ecde57f03d8fa4ba78d29793447f70e717"}, - {file = "regex-2026.4.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c228cf65b4a54583763645dcd73819b3b381ca8b4bb1b349dee1c135f4112c07"}, - {file = "regex-2026.4.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dd2630faeb6876fb0c287f664d93ddce4d50cd46c6e88e60378c05c9047e08ca"}, - {file = "regex-2026.4.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6a50ab11b7779b849472337191f3a043e27e17f71555f98d0092fa6d73364520"}, - {file = "regex-2026.4.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0734f63afe785138549fbe822a8cfeaccd1bae814c5057cc0ed5b9f2de4fc883"}, - {file = "regex-2026.4.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4ee50606cb1967db7e523224e05f32089101945f859928e65657a2cbb3d278b"}, - {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6c1818f37be3ca02dcb76d63f2c7aaba4b0dc171b579796c6fbe00148dfec6b1"}, - {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f5bfc2741d150d0be3e4a0401a5c22b06e60acb9aa4daa46d9e79a6dcd0f135b"}, - {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:504ffa8a03609a087cad81277a629b6ce884b51a24bd388a7980ad61748618ff"}, - {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70aadc6ff12e4b444586e57fc30771f86253f9f0045b29016b9605b4be5f7dfb"}, - {file = "regex-2026.4.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f4f83781191007b6ef43b03debc35435f10cad9b96e16d147efe84a1d48bdde4"}, - {file = "regex-2026.4.4-cp313-cp313t-win32.whl", hash = "sha256:e014a797de43d1847df957c0a2a8e861d1c17547ee08467d1db2c370b7568baa"}, - {file = "regex-2026.4.4-cp313-cp313t-win_amd64.whl", hash = "sha256:b15b88b0d52b179712632832c1d6e58e5774f93717849a41096880442da41ab0"}, - {file = "regex-2026.4.4-cp313-cp313t-win_arm64.whl", hash = "sha256:586b89cdadf7d67bf86ae3342a4dcd2b8d70a832d90c18a0ae955105caf34dbe"}, - {file = "regex-2026.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2da82d643fa698e5e5210e54af90181603d5853cf469f5eedf9bfc8f59b4b8c7"}, - {file = "regex-2026.4.4-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:54a1189ad9d9357760557c91103d5e421f0a2dabe68a5cdf9103d0dcf4e00752"}, - {file = "regex-2026.4.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:76d67d5afb1fe402d10a6403bae668d000441e2ab115191a804287d53b772951"}, - {file = "regex-2026.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e7cd3e4ee8d80447a83bbc9ab0c8459781fa77087f856c3e740d7763be0df27f"}, - {file = "regex-2026.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e19e18c568d2866d8b6a6dfad823db86193503f90823a8f66689315ba28fbe8"}, - {file = "regex-2026.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7698a6f38730fd1385d390d1ed07bb13dce39aa616aca6a6d89bea178464b9a4"}, - {file = "regex-2026.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:173a66f3651cdb761018078e2d9487f4cf971232c990035ec0eb1cdc6bf929a9"}, - {file = "regex-2026.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fa7922bbb2cc84fa062d37723f199d4c0cd200245ce269c05db82d904db66b83"}, - {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:59f67cd0a0acaf0e564c20bbd7f767286f23e91e2572c5703bf3e56ea7557edb"}, - {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:475e50f3f73f73614f7cba5524d6de49dee269df00272a1b85e3d19f6d498465"}, - {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:a1c0c7d67b64d85ac2e1879923bad2f08a08f3004055f2f406ef73c850114bd4"}, - {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:1371c2ccbb744d66ee63631cc9ca12aa233d5749972626b68fe1a649dd98e566"}, - {file = "regex-2026.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:59968142787042db793348a3f5b918cf24ced1f23247328530e063f89c128a95"}, - {file = "regex-2026.4.4-cp314-cp314-win32.whl", hash = "sha256:59efe72d37fd5a91e373e5146f187f921f365f4abc1249a5ab446a60f30dd5f8"}, - {file = "regex-2026.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:e0aab3ff447845049d676827d2ff714aab4f73f340e155b7de7458cf53baa5a4"}, - {file = "regex-2026.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:a7a5bb6aa0cf62208bb4fa079b0c756734f8ad0e333b425732e8609bd51ee22f"}, - {file = "regex-2026.4.4-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:97850d0638391bdc7d35dc1c1039974dcb921eaafa8cc935ae4d7f272b1d60b3"}, - {file = "regex-2026.4.4-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ee7337f88f2a580679f7bbfe69dc86c043954f9f9c541012f49abc554a962f2e"}, - {file = "regex-2026.4.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7429f4e6192c11d659900c0648ba8776243bf396ab95558b8c51a345afeddde6"}, - {file = "regex-2026.4.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4f10fbd5dd13dcf4265b4cc07d69ca70280742870c97ae10093e3d66000359"}, - {file = "regex-2026.4.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a152560af4f9742b96f3827090f866eeec5becd4765c8e0d3473d9d280e76a5a"}, - {file = "regex-2026.4.4-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54170b3e95339f415d54651f97df3bff7434a663912f9358237941bbf9143f55"}, - {file = "regex-2026.4.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:07f190d65f5a72dcb9cf7106bfc3d21e7a49dd2879eda2207b683f32165e4d99"}, - {file = "regex-2026.4.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9a2741ce5a29d3c84b0b94261ba630ab459a1b847a0d6beca7d62d188175c790"}, - {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b26c30df3a28fd9793113dac7385a4deb7294a06c0f760dd2b008bd49a9139bc"}, - {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:421439d1bee44b19f4583ccf42670ca464ffb90e9fdc38d37f39d1ddd1e44f1f"}, - {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b40379b53ecbc747fd9bdf4a0ea14eb8188ca1bd0f54f78893a39024b28f4863"}, - {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:08c55c13d2eef54f73eeadc33146fb0baaa49e7335eb1aff6ae1324bf0ddbe4a"}, - {file = "regex-2026.4.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9776b85f510062f5a75ef112afe5f494ef1635607bf1cc220c1391e9ac2f5e81"}, - {file = "regex-2026.4.4-cp314-cp314t-win32.whl", hash = "sha256:385edaebde5db5be103577afc8699fea73a0e36a734ba24870be7ffa61119d74"}, - {file = "regex-2026.4.4-cp314-cp314t-win_amd64.whl", hash = "sha256:5d354b18839328927832e2fa5f7c95b7a3ccc39e7a681529e1685898e6436d45"}, - {file = "regex-2026.4.4-cp314-cp314t-win_arm64.whl", hash = "sha256:af0384cb01a33600c49505c27c6c57ab0b27bf84a74e28524c92ca897ebdac9d"}, - {file = "regex-2026.4.4.tar.gz", hash = "sha256:e08270659717f6973523ce3afbafa53515c4dc5dcad637dc215b6fd50f689423"}, + {file = "regex-2026.7.19-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:555497390743af1a65045fa4527782d10ff5b88970359412baa4a1e628fe393b"}, + {file = "regex-2026.7.19-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:343a4504e3fb688c47cad451221ca5d4814f42b1e16c0065bde9cbf7f473bd52"}, + {file = "regex-2026.7.19-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ebee1ee89c39c953baac6924fcde08c5bb427c4057510862f9d7c7bdb3d8665"}, + {file = "regex-2026.7.19-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:062f8cb7a9739c4835d22bd96f370c59aba89f257adcfa53be3cc209e08d3ae0"}, + {file = "regex-2026.7.19-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1123ef4211d763ee771d47916a1596e2f4915794f7aabdc1adcb20e4249a6951"}, + {file = "regex-2026.7.19-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6e44c0e7c5664be20aee92085153150c0a7967310a73a43c0f832b7cd35d0dd3"}, + {file = "regex-2026.7.19-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98c6ac18480fcdb33f35439183f1d2e79760ab41930309c6d951cb1f8e46694c"}, + {file = "regex-2026.7.19-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4458124d71339f505bf1fb94f69fd1bb8fa9d2481eebfef27c10ef4f2b9e12f6"}, + {file = "regex-2026.7.19-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fbf300e2070bb35038660b3be1be4b91b0024edb41517e6996320b49b92b4175"}, + {file = "regex-2026.7.19-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b2b506b1788df5fecd270a10d5e70a95fe77b87ea2b370a318043f6f5f817ee6"}, + {file = "regex-2026.7.19-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:52579c60a6078be70a0e49c81d6e56d677f34cd439af281a0083b8c7bc75c095"}, + {file = "regex-2026.7.19-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:2955907b7157a6660f27079edf7e0229e9c9c5325c77a2ef6a890cba91efa6f0"}, + {file = "regex-2026.7.19-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:89dfee3319f5ae3f75ebd5c2445a809bb320252ba5529ffdafea4ef25d79cf1a"}, + {file = "regex-2026.7.19-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d3143f159261b1ce5b24c261c590e5913370c3200c5e9ebbb92b5aa5e111902"}, + {file = "regex-2026.7.19-cp310-cp310-win32.whl", hash = "sha256:64729333167c2dcaaa56a331d40ee097bd9c5617ffd51dabb09eaddafb1b532e"}, + {file = "regex-2026.7.19-cp310-cp310-win_amd64.whl", hash = "sha256:1c398716054621aa300b3d411f467dda903806c5da0df6945ab73982b8d115db"}, + {file = "regex-2026.7.19-cp310-cp310-win_arm64.whl", hash = "sha256:064f1760a5a4ade65c5419be23e782f29147528e8a66e0c42dd4cedb8d4e9fc6"}, + {file = "regex-2026.7.19-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ac777001cdfc28b72477d93c8564bb7583081ea8fb45cdca3d568e0a4f87183c"}, + {file = "regex-2026.7.19-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:59787bd5f8c70aa339084e961d2996b53fbdeab4d5393bba5c1fe1fc32e02bae"}, + {file = "regex-2026.7.19-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:90c633e7e8d6bf4e992b8b36ce69e018f834b641dd6de8cea6d78c06ffa119c5"}, + {file = "regex-2026.7.19-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:87ccab0db8d5f4fbb0272642113c1adb2ffc698c16d3a0944580222331fa7a20"}, + {file = "regex-2026.7.19-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e50d748a32da622f256e8d505867f5d3c43a837c6a9f0efb149655fadd1042a"}, + {file = "regex-2026.7.19-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bf1516fe58fc104f39b2d1dbe2d5e27d0cd45c4be2e42ba6ee0cc763701ec3c7"}, + {file = "regex-2026.7.19-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09f3e5287f94f17b709dc9a9e70865855feee835c861613be144218ce4ca82cc"}, + {file = "regex-2026.7.19-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6383cd2ed53a646c659ba1fe65727db76437fdaa069e697a0b44a51d5843d864"}, + {file = "regex-2026.7.19-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:09d3007fc76249a83cdd33de160d50e6cb77f54e09d8fa9e7148e10607ce24af"}, + {file = "regex-2026.7.19-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f8c6e7a1cfa3dc9d0ee2de0e65e834537fa29992cc3976ffec914afc35c5dd5"}, + {file = "regex-2026.7.19-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:b2ea4a3e8357be8849e833beeae757ac3c7a6b3fc055c03c808a53c91ad30d82"}, + {file = "regex-2026.7.19-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:80115dd39481fd3a4b4080220799dbcacb921a844de4b827264ececacbe17c78"}, + {file = "regex-2026.7.19-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d6ce43a0269d68cee79a7d1ade7def53c20f8f2a047b92d7b5d5bcc73ae88327"}, + {file = "regex-2026.7.19-cp311-cp311-win32.whl", hash = "sha256:9be2a6647740dd3cca6acb24e87f03d7632cd280dbce9bbe40c26353a215a45d"}, + {file = "regex-2026.7.19-cp311-cp311-win_amd64.whl", hash = "sha256:8d3469c91dd92ee41b7c95280edbd975ef1ba9195086686623a1c6e8935ce965"}, + {file = "regex-2026.7.19-cp311-cp311-win_arm64.whl", hash = "sha256:36aacfb15faaff3ced55afbf35ec72f50d4aee22082c4f7fe0573a33e2fca92e"}, + {file = "regex-2026.7.19-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2cc3460cedf7579948486eab03bc9ad7089df4d7281c0f47f4afe03e8d13f02d"}, + {file = "regex-2026.7.19-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0e9554c8785eac5cffe6300f69a91f58ba72bc88a5f8d661235ad7c6aa5b8ccd"}, + {file = "regex-2026.7.19-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d7da47a0f248977f08e2cb659ff3c17ddc13a4d39b3a7baa0a81bf5b415430f6"}, + {file = "regex-2026.7.19-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93db40c8de0815baab96a06e08a984bac71f989d13bab789e382158c5d426797"}, + {file = "regex-2026.7.19-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:66bd62c59a5427746e8c44becae1d9b99d22fb13f30f492083dfb9ad7c45cc18"}, + {file = "regex-2026.7.19-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1649eb39fcc9ea80c4d2f110fde2b8ab2aef3877b98f02ab9b14e961f418c511"}, + {file = "regex-2026.7.19-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9dce8ec9695f531a1b8a6f314fd4b393adcccf2ea861db480cdf97a301d01a68"}, + {file = "regex-2026.7.19-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3080a7fd38ef049bd489e01c970c97dd84ff446a885b0f1f6b26d9b1ad13ce11"}, + {file = "regex-2026.7.19-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1d793a7988e04fcb1e2e135567443d82173225d657419ec09414a9b5a145b986"}, + {file = "regex-2026.7.19-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e8b0abe7d870f53ca5143895fef7d1041a0c831a140d3dc2c760dd7ba25d4a8b"}, + {file = "regex-2026.7.19-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:4e5413bd5f13d3a4e3539ca98f70f75e7fca92518dd7f117f030ebedd10b60cb"}, + {file = "regex-2026.7.19-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:73b133a9e6fb512858e7f065e96f1180aa46646bc74a83aea62f1d314f3dd035"}, + {file = "regex-2026.7.19-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dbe6493fbd27321b1d1f2dd4f5c7e5bd4d8b1d7cab7f32fd67db3d0b2ed8248a"}, + {file = "regex-2026.7.19-cp312-cp312-win32.whl", hash = "sha256:ddd67571c10869f65a5d7dde536d1e066e306cc90de57d7de4d5f34802428bb5"}, + {file = "regex-2026.7.19-cp312-cp312-win_amd64.whl", hash = "sha256:e30d40268a28d54ce0437031750497004c22602b8e3ab891f759b795a003b312"}, + {file = "regex-2026.7.19-cp312-cp312-win_arm64.whl", hash = "sha256:de9208bb427130c82a5dbfd104f92c8876fc9559278c880b3002755bbbe9c83d"}, + {file = "regex-2026.7.19-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f035d9dc1d25eff9d361456572231c7d27b5ccd473ca7dc0adfce732bd006d40"}, + {file = "regex-2026.7.19-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c42572142ed0b9d5d261ba727157c426510da78e20828b66bbb855098b8a4e38"}, + {file = "regex-2026.7.19-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40b34dd88658e4fedd2fddbf0275ac970d00614b731357f425722a3ed1983d11"}, + {file = "regex-2026.7.19-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c41c63992bf1874cebb6e7f56fd7d3c007924659a604ae3d90e427d40d4fd13"}, + {file = "regex-2026.7.19-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1d3372064506b94dd2c67c845f2db8062e9e9ba84d04e33cb96d7d33c11fe1ae"}, + {file = "regex-2026.7.19-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fce7760bf283405b2c7999cab3da4e72f7deca6396013115e3f7a955db9760da"}, + {file = "regex-2026.7.19-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c0d702548d89d572b2929879bc883bb7a4c4709efafe4512cadee56c55c9bd15"}, + {file = "regex-2026.7.19-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d446c6ac40bb6e05025ccee55b84d80fe9bf8e93010ffc4bb9484f13d498835f"}, + {file = "regex-2026.7.19-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4c3501bfa814ab07b5580741f9bf78dfdfe146a04057f82df9e2402d2a975939"}, + {file = "regex-2026.7.19-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c4585c3e64b4f9e583b4d2683f18f5d5d872b3d71dcf24594b74ecc23602fa96"}, + {file = "regex-2026.7.19-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:571fde9741eb0ccde23dd4e0c1d50fbae910e901fa7e629faf39b2dda740d220"}, + {file = "regex-2026.7.19-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:15b364b9b98d6d2fe1a85034c23a3180ff913f46caddc3895f6fd65186255ccc"}, + {file = "regex-2026.7.19-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffd8893ccc1c2fce6e0d6ca402d716fe1b29db70c7132609a05955e31b2aa8f2"}, + {file = "regex-2026.7.19-cp313-cp313-win32.whl", hash = "sha256:f0fa4fa9c3632d708742baf2282f2055c11d888a790362670a403cbf48a2c404"}, + {file = "regex-2026.7.19-cp313-cp313-win_amd64.whl", hash = "sha256:d51ffd3427640fa2da6ade574ceba932f210ad095f65fcc450a2b0a0d454868e"}, + {file = "regex-2026.7.19-cp313-cp313-win_arm64.whl", hash = "sha256:c670fe7be5b6020b76bc6e8d2196074657e1327595bca93a389e1a76ab130ad8"}, + {file = "regex-2026.7.19-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db47b561c9afd884baa1f96f797c9ca369872c4b65912bc691cfa99e68340af2"}, + {file = "regex-2026.7.19-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:65dcd28d3eba2ab7c2fd906485cc301392b47cc2234790d27d4e4814e02cdfda"}, + {file = "regex-2026.7.19-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f2e7f8e2ab6c2922be02c7ec45185aa5bd771e2e57b95455ee343a44d8130dff"}, + {file = "regex-2026.7.19-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe31f28c94402043161876a258a9c6f757cb485905c7614ce8d6cd40e6b7bdc1"}, + {file = "regex-2026.7.19-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f8f6fa298bb4f7f58a33334406218ba74716e68feddf5e4e54cd5d8082705abf"}, + {file = "regex-2026.7.19-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:cc1b2440423a851fad781309dd87843868f4f66a6bcd1ddb9225cf4ec2c84732"}, + {file = "regex-2026.7.19-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ac59a0900474a52b7c04af8196affc22bd9842acb0950df12f7b813e983609a"}, + {file = "regex-2026.7.19-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4896db1f4ce0576765b8272aa922df324e0f5b9bb2c3d03044ff32a7234a9aba"}, + {file = "regex-2026.7.19-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4e6883a021db30511d9fb8cfb0f222ce1f2c369f7d4d8b0448f449a93ba0bdfc"}, + {file = "regex-2026.7.19-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:09523a592938aa9f587fb74467c63ff0cf88fc3df14c82ab0f0517dcf76aaa62"}, + {file = "regex-2026.7.19-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:1ebac3474b8589fce2f9b225b650afd61448f7c73a5d0255a10cc6366471aed1"}, + {file = "regex-2026.7.19-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:4a0530bb1b8c1c985e7e2122e2b4d3aedd8a3c21c6bfddae6767c4405668b56e"}, + {file = "regex-2026.7.19-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2ef7eeb108c47ce7bcc9513e51bcb1bf57e8f483d52fce68a8642e3527141ae0"}, + {file = "regex-2026.7.19-cp313-cp313t-win32.whl", hash = "sha256:64b6ca7391a1395c2638dd5c7456d67bea44fc6c5e8e92c5dc8aa6a8f23292b4"}, + {file = "regex-2026.7.19-cp313-cp313t-win_amd64.whl", hash = "sha256:f04b9f56b0e0614c0126be12c2c2d9f8850c1e57af302bd0a63bed379d4af974"}, + {file = "regex-2026.7.19-cp313-cp313t-win_arm64.whl", hash = "sha256:fcee38cd8e5089d6d4f048ba1233b3ad76e5954f545382180889112ff5cb712d"}, + {file = "regex-2026.7.19-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:a81758ed242b861b72e778ba34d41366441a2e10b16b472784c88da2dea7e2dd"}, + {file = "regex-2026.7.19-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4aa5435cdb3eb6f55fe98a171b05e3fbcd95fadaa4aa32acf62afd9b0cfdbcac"}, + {file = "regex-2026.7.19-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:60be8693a1dadc210bbcbc0db3e26da5f7d01d1d5a3da594e99b4fa42df404f5"}, + {file = "regex-2026.7.19-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d19662dbedbe783d323196312d38f5ba53cf56296378252171985da6899887d3"}, + {file = "regex-2026.7.19-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d15df07081d91b76ff20d43f94592ee110330152d617b730fdbe5ef9fb680053"}, + {file = "regex-2026.7.19-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:56ad4d9f77df871a99e25c37091052a02528ec0eb059de928ee33956b854b45b"}, + {file = "regex-2026.7.19-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7322ec6cc9fba9d49ab888bb82d67ac5625627aa168f0165139b17018df3fb8a"}, + {file = "regex-2026.7.19-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9c7472192ebfad53a6be7c4a8bfb2d64b81c0e93a1fc8c57e1dd0b638297b5d1"}, + {file = "regex-2026.7.19-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c10b82c2634df08dfb13b1f04e38fe310d086ee092f4f69c0c8da234251e556e"}, + {file = "regex-2026.7.19-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:17ed5692f6acc4183e98331101a5f9e4f64d72fe58b753da4d444a2c77d05b12"}, + {file = "regex-2026.7.19-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:22a992de9a0d91bda927bf02b94351d737a0302905432c88a53de7c4b9ce62e2"}, + {file = "regex-2026.7.19-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:618a0aed532be87294c4477b0481f3aa0f1520f4014a4374dd4cf789b4cd2c97"}, + {file = "regex-2026.7.19-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2ce9e679f776649746729b6c86382da519ef649c8e34cc41df0d2e5e0f6c36d4"}, + {file = "regex-2026.7.19-cp314-cp314-win32.whl", hash = "sha256:73f272fba87b8ccfe70a137d02a54af386f6d27aa509fbffdd978f5947aae1aa"}, + {file = "regex-2026.7.19-cp314-cp314-win_amd64.whl", hash = "sha256:d721e53758b2cca74990185eb0671dd466d7a388a1a45d0c6f4c13cef41a68ac"}, + {file = "regex-2026.7.19-cp314-cp314-win_arm64.whl", hash = "sha256:65fa6cb38ed5e9c3637e68e544f598b39c3b86b808ed0627a67b68320384b459"}, + {file = "regex-2026.7.19-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:5a2721c8720e2cb3c209925dfb9200199b4b07361c9e01d321719404b21458b3"}, + {file = "regex-2026.7.19-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:199535629f25caf89698039af3d1ad5fcae7f933e2112c73f1cdf49165c99518"}, + {file = "regex-2026.7.19-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9b60d7814174f059e5de4ab98271cc5ba9259cfea55273a81544dceea32dc8d9"}, + {file = "regex-2026.7.19-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dbece16025afda5e3031af0c4059207e61dcf73ef13af844964f57f387d1c435"}, + {file = "regex-2026.7.19-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d24ecb4f5e009ea0bd275ee37ad9953b32005e2e5e60f8bbae16da0dbbf0d3a0"}, + {file = "regex-2026.7.19-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8cae6fd77a5b72dae505084b1a2ee0360139faf72fedbab667cd7cc65aae7a6a"}, + {file = "regex-2026.7.19-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9724e6cb5e478cd7d8cabf027826178739cb18cf0e117d0e32814d479fa02276"}, + {file = "regex-2026.7.19-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:572fc57b0009c735ee56c175ea021b637a15551a312f56734277f923d6fd0f6c"}, + {file = "regex-2026.7.19-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:20568e182eb82d39a6bf7cff3fd58566f14c75c6f74b2c8c96537eecf9010e3a"}, + {file = "regex-2026.7.19-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:1d58561843f0ff7dc78b4c28b5e2dc388f3eff94ebc8a232a3adba961fc00009"}, + {file = "regex-2026.7.19-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:61bb1bd45520aacd56dd80943bd34991fb5350afdd1f36f2282230fd5154a218"}, + {file = "regex-2026.7.19-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:cd3584591ea4429026cdb931b054342c2bcf189b44ff367f8d5c15bc092a2966"}, + {file = "regex-2026.7.19-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5cc26a66e212fa5d6c6170c3a40d99d888db3020c6fdab1523250d4341382e44"}, + {file = "regex-2026.7.19-cp314-cp314t-win32.whl", hash = "sha256:2c4e61e2e1be56f63ec3cc618aa9e0de81ef6f43d177205451840022e24f5b78"}, + {file = "regex-2026.7.19-cp314-cp314t-win_amd64.whl", hash = "sha256:c639ea314df70a7b2811e8020448c75af8c9445f5a60f8a4ced81c306a9380c2"}, + {file = "regex-2026.7.19-cp314-cp314t-win_arm64.whl", hash = "sha256:9a15e785f244f3e07847b984ce8773fc3da10a9f3c131cc49a4c5b4d672b4547"}, + {file = "regex-2026.7.19.tar.gz", hash = "sha256:7e77b324909c1617cbb4c668677e2c6ae13f44d7c1de0d4f15f2e3c10f3315b5"}, ] [[package]] @@ -6020,206 +5788,187 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<8)"] [[package]] name = "requirements-parser" -version = "0.13.0" +version = "0.13.1" description = "This is a small Python module for parsing Pip requirement files." optional = false python-versions = "<4.0,>=3.8" groups = ["dev"] files = [ - {file = "requirements_parser-0.13.0-py3-none-any.whl", hash = "sha256:2b3173faecf19ec5501971b7222d38f04cb45bb9d87d0ad629ca71e2e62ded14"}, - {file = "requirements_parser-0.13.0.tar.gz", hash = "sha256:0843119ca2cb2331de4eb31b10d70462e39ace698fd660a915c247d2301a4418"}, + {file = "requirements_parser-0.13.1-py3-none-any.whl", hash = "sha256:6e385663eb32589d16e5b22bb6e5251a57908e73803ffff438b53cd6ea2056e0"}, + {file = "requirements_parser-0.13.1.tar.gz", hash = "sha256:78811383b2089b6c5197a1431bc2c12ff950245edca39a23eea3460782038dd3"}, ] [package.dependencies] packaging = ">=23.2" -[[package]] -name = "rich" -version = "15.0.0" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.9.0" -groups = ["main"] -markers = "python_version < \"3.14\"" -files = [ - {file = "rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb"}, - {file = "rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - [[package]] name = "rpds-py" -version = "0.30.0" +version = "2026.6.3" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false -python-versions = ">=3.10" +python-versions = ">=3.11" groups = ["main", "dev"] files = [ - {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, - {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389a2d49eded1896c3d48b0136ead37c48e221b391c052fba3f4055c367f60a6"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:32c8528634e1bf7121f3de08fa85b138f4e0dc47657866630611b03967f041d7"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f207f69853edd6f6700b86efb84999651baf3789e78a466431df1331608e5324"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:67b02ec25ba7a9e8fa74c63b6ca44cf5707f2fbfadae3ee8e7494297d56aa9df"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0e95f6819a19965ff420f65578bacb0b00f251fefe2c8b23347c37174271f3"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:a452763cc5198f2f98898eb98f7569649fe5da666c2dc6b5ddb10fde5a574221"}, - {file = "rpds_py-0.30.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0b65193a413ccc930671c55153a03ee57cecb49e6227204b04fae512eb657a7"}, - {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:858738e9c32147f78b3ac24dc0edb6610000e56dc0f700fd5f651d0a0f0eb9ff"}, - {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:da279aa314f00acbb803da1e76fa18666778e8a8f83484fba94526da5de2cba7"}, - {file = "rpds_py-0.30.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7c64d38fb49b6cdeda16ab49e35fe0da2e1e9b34bc38bd78386530f218b37139"}, - {file = "rpds_py-0.30.0-cp310-cp310-win32.whl", hash = "sha256:6de2a32a1665b93233cde140ff8b3467bdb9e2af2b91079f0333a0974d12d464"}, - {file = "rpds_py-0.30.0-cp310-cp310-win_amd64.whl", hash = "sha256:1726859cd0de969f88dc8673bdd954185b9104e05806be64bcd87badbe313169"}, - {file = "rpds_py-0.30.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a2bffea6a4ca9f01b3f8e548302470306689684e61602aa3d141e34da06cf425"}, - {file = "rpds_py-0.30.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc4f992dfe1e2bc3ebc7444f6c7051b4bc13cd8e33e43511e8ffd13bf407010d"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:422c3cb9856d80b09d30d2eb255d0754b23e090034e1deb4083f8004bd0761e4"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99b47d6ad9a6da00bec6aabe5a6279ecd3c06a329d4aa4771034a21e335c3a97"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33f559f3104504506a44bb666b93a33f5d33133765b0c216a5bf2f1e1503af89"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:946fe926af6e44f3697abbc305ea168c2c31d3e3ef1058cf68f379bf0335a78d"}, - {file = "rpds_py-0.30.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:495aeca4b93d465efde585977365187149e75383ad2684f81519f504f5c13038"}, - {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0ca5da0386dee0655b4ccdf46119df60e0f10da268d04fe7cc87886872ba7"}, - {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8d6d1cc13664ec13c1b84241204ff3b12f9bb82464b8ad6e7a5d3486975c2eed"}, - {file = "rpds_py-0.30.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3896fa1be39912cf0757753826bc8bdc8ca331a28a7c4ae46b7a21280b06bb85"}, - {file = "rpds_py-0.30.0-cp311-cp311-win32.whl", hash = "sha256:55f66022632205940f1827effeff17c4fa7ae1953d2b74a8581baaefb7d16f8c"}, - {file = "rpds_py-0.30.0-cp311-cp311-win_amd64.whl", hash = "sha256:a51033ff701fca756439d641c0ad09a41d9242fa69121c7d8769604a0a629825"}, - {file = "rpds_py-0.30.0-cp311-cp311-win_arm64.whl", hash = "sha256:47b0ef6231c58f506ef0b74d44e330405caa8428e770fec25329ed2cb971a229"}, - {file = "rpds_py-0.30.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a161f20d9a43006833cd7068375a94d035714d73a172b681d8881820600abfad"}, - {file = "rpds_py-0.30.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6abc8880d9d036ecaafe709079969f56e876fcf107f7a8e9920ba6d5a3878d05"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca28829ae5f5d569bb62a79512c842a03a12576375d5ece7d2cadf8abe96ec28"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1010ed9524c73b94d15919ca4d41d8780980e1765babf85f9a2f90d247153dd"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8d1736cfb49381ba528cd5baa46f82fdc65c06e843dab24dd70b63d09121b3f"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d948b135c4693daff7bc2dcfc4ec57237a29bd37e60c2fabf5aff2bbacf3e2f1"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f236970bccb2233267d89173d3ad2703cd36a0e2a6e92d0560d333871a3d23"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2e6ecb5a5bcacf59c3f912155044479af1d0b6681280048b338b28e364aca1f6"}, - {file = "rpds_py-0.30.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a8fa71a2e078c527c3e9dc9fc5a98c9db40bcc8a92b4e8858e36d329f8684b51"}, - {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73c67f2db7bc334e518d097c6d1e6fed021bbc9b7d678d6cc433478365d1d5f5"}, - {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5ba103fb455be00f3b1c2076c9d4264bfcb037c976167a6047ed82f23153f02e"}, - {file = "rpds_py-0.30.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7cee9c752c0364588353e627da8a7e808a66873672bcb5f52890c33fd965b394"}, - {file = "rpds_py-0.30.0-cp312-cp312-win32.whl", hash = "sha256:1ab5b83dbcf55acc8b08fc62b796ef672c457b17dbd7820a11d6c52c06839bdf"}, - {file = "rpds_py-0.30.0-cp312-cp312-win_amd64.whl", hash = "sha256:a090322ca841abd453d43456ac34db46e8b05fd9b3b4ac0c78bcde8b089f959b"}, - {file = "rpds_py-0.30.0-cp312-cp312-win_arm64.whl", hash = "sha256:669b1805bd639dd2989b281be2cfd951c6121b65e729d9b843e9639ef1fd555e"}, - {file = "rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2"}, - {file = "rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e"}, - {file = "rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d"}, - {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7"}, - {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31"}, - {file = "rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95"}, - {file = "rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d"}, - {file = "rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15"}, - {file = "rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1"}, - {file = "rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a"}, - {file = "rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9"}, - {file = "rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0"}, - {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94"}, - {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08"}, - {file = "rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27"}, - {file = "rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6"}, - {file = "rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d"}, - {file = "rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0"}, - {file = "rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07"}, - {file = "rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f"}, - {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65"}, - {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f"}, - {file = "rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53"}, - {file = "rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed"}, - {file = "rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950"}, - {file = "rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6"}, - {file = "rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb"}, - {file = "rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8"}, - {file = "rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5"}, - {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404"}, - {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856"}, - {file = "rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40"}, - {file = "rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0"}, - {file = "rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c2262bdba0ad4fc6fb5545660673925c2d2a5d9e2e0fb603aad545427be0fc58"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ee6af14263f25eedc3bb918a3c04245106a42dfd4f5c2285ea6f997b1fc3f89a"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3adbb8179ce342d235c31ab8ec511e66c73faa27a47e076ccc92421add53e2bb"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:250fa00e9543ac9b97ac258bd37367ff5256666122c2d0f2bc97577c60a1818c"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9854cf4f488b3d57b9aaeb105f06d78e5529d3145b1e4a41750167e8c213c6d3"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:993914b8e560023bc0a8bf742c5f303551992dcb85e247b1e5c7f4a7d145bda5"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58edca431fb9b29950807e301826586e5bbf24163677732429770a697ffe6738"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:dea5b552272a944763b34394d04577cf0f9bd013207bc32323b5a89a53cf9c2f"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ba3af48635eb83d03f6c9735dfb21785303e73d22ad03d489e88adae6eab8877"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:dff13836529b921e22f15cb099751209a60009731a68519630a24d61f0b1b30a"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1b151685b23929ab7beec71080a8889d4d6d9fa9a983d213f07121205d48e2c4"}, - {file = "rpds_py-0.30.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ac37f9f516c51e5753f27dfdef11a88330f04de2d564be3991384b2f3535d02e"}, - {file = "rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84"}, + {file = "rpds_py-2026.6.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7b689145a1485c335569bd056464f3243a29af7ed3871c7be31ad624ba239bc7"}, + {file = "rpds_py-2026.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db08f45aecde626498fb3df07bcf6d2ec040af42e859a4f5040d79c200342911"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc992ab27b15f852c76755eb2ab7dce86585ddadba6fa5946e58556088845b4"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f88d653e7b3b779d71ae7454e20dcc9b6bae903f33c269db9f2be41bda3f261"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e52655eaf81e32593abedaa4bfe33170c8cfedf3365ed9be6e11e07f148f0278"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dfcc8b909769d19db55c7cc9541eb64b9b774b1057ffffb4f1048070475bb9f9"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c1255b302953c86a486b81d330d5ee1d5bd937691ce271b6be0ef0e299eaab7"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:8d2294a31386bfa251d8c8a39472beee17db67d4f1a6eabea665d35c9a4461c3"}, + {file = "rpds_py-2026.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8f23ead891a3b762f35ab3b04623da7056545b48aa60d59957e6789914545da"}, + {file = "rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:421aba32367055614287a4292b6a17f1939c9452299f7a0209c117e990b646d4"}, + {file = "rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1e5822dfc2f0d4ab7e745eaa6d85945069329beeccef965af3f3bb26058fcab6"}, + {file = "rpds_py-2026.6.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83e35b57523816c8613fd0776b40cd8bb9f596b37ddd2692eb4a6bb5ab2f8c93"}, + {file = "rpds_py-2026.6.3-cp311-cp311-win32.whl", hash = "sha256:de3eceba0b683bcbb1ab93da016d0270df1f9ae7be716b40214c5dafac6ea45a"}, + {file = "rpds_py-2026.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:2c54a076ca4d370980ab57bc0e31df57bbe8d41340436a90ef8b1219a3cbb127"}, + {file = "rpds_py-2026.6.3-cp311-cp311-win_arm64.whl", hash = "sha256:168c733a7112e071bb7a66460e667edfcff06c017a3c523f7a8a8e08d0140804"}, + {file = "rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0"}, + {file = "rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a"}, + {file = "rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4"}, + {file = "rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa"}, + {file = "rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc"}, + {file = "rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822"}, + {file = "rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed"}, + {file = "rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f"}, + {file = "rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96"}, + {file = "rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223"}, + {file = "rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885"}, + {file = "rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4"}, + {file = "rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7"}, + {file = "rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d"}, + {file = "rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97"}, + {file = "rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0"}, + {file = "rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80"}, + {file = "rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb"}, + {file = "rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e"}, + {file = "rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc"}, + {file = "rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77"}, + {file = "rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698"}, + {file = "rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd"}, + {file = "rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d"}, + {file = "rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8"}, + {file = "rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5"}, + {file = "rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e"}, + {file = "rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2"}, + {file = "rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13"}, + {file = "rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a"}, + {file = "rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868"}, + {file = "rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187"}, + {file = "rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107"}, + {file = "rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba"}, + {file = "rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369"}, + {file = "rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146"}, + {file = "rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577"}, + {file = "rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:4cf2d36a2357e4d07bb5a4f98801265327b48256867816cfd2ceb001e9754a8f"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30c6dc199b24a5e3e81d50da0f00858c5bbdb2617a750395687f4339c5818171"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9891e594296ab9dada6551c8e7b387b2721f27a67eecd528412e8906247a7b90"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5c2dc92304aa48a4a60443b548bb12f12e119d4b72f314015e67b9e1be97fca"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:127e08c0642d880cf32ca47ec2a4a77b901f7e2dd1ad9762adb13955d72ffcc9"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8bb68f03f395eb793220b45c097bd4d8c32944393da0fad8b999efac0868fc8c"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3450b693fde92133e9f51060568a4c31fcca76d5e53bbd611e689ca446517e9"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:5e8d07bddee435a2ff6f1920e18feff28d0bc4533e42f4bf6927fbd073312c41"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3a83ae6c67b7676b9878378547ca8e93ed77a580037bcbcd1d32f739e1e6089c"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2bfd04c19ddbd6640de0b51894d764bd2758854d5b75bd102d2ef10cb9c293a9"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:ca6546b66be9dc4738b1b043d5ebd5488c66c578c5ff0fd0e8065313fe3afb76"}, + {file = "rpds_py-2026.6.3-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8e65860d238379ed982fd9ba690579b5e95af2f4840f99c772816dbe573cb826"}, + {file = "rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4"}, ] [[package]] name = "ruff" -version = "0.15.12" +version = "0.15.22" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "ruff-0.15.12-py3-none-linux_armv6l.whl", hash = "sha256:f86f176e188e94d6bdbc09f09bfd9dc729059ad93d0e7390b5a73efe19f8861c"}, - {file = "ruff-0.15.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e3bcd123364c3770b8e1b7baaf343cc99a35f197c5c6e8af79015c666c423a6c"}, - {file = "ruff-0.15.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fe87510d000220aa1ed530d4448a7c696a0cae1213e5ec30e5874287b66557b5"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84a1630093121375a3e2a95b4a6dc7b59e2b4ee76216e32d81aae550a832d002"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fb129f40f114f089ebe0ca56c0d251cf2061b17651d464bb6478dc01e69f11f5"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0c862b172d695db7598426b8af465e7e9ac00a3ea2a3630ee67eb82e366aaa6"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2849ea9f3484c3aca43a82f484210370319e7170df4dfe4843395ddf6c57bc33"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e77c7e51c07fe396826d5969a5b846d9cd4c402535835fb6e21ce8b28fef847"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b2f4f2f3b1026b5fb449b467d9264bf22067b600f7b6f41fc5958909f449d0"}, - {file = "ruff-0.15.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9ba3b8f1afd7e2e43d8943e55f249e13f9682fde09711644a6e7290eb4f3e339"}, - {file = "ruff-0.15.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e852ba9fdc890655e1d78f2df1499efbe0e54126bd405362154a75e2bde159c5"}, - {file = "ruff-0.15.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dd8aed930da53780d22fc70bdf84452c843cf64f8cb4eb38984319c24c5cd5fd"}, - {file = "ruff-0.15.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:01da3988d225628b709493d7dc67c3b9b12c0210016b08690ef9bd27970b262b"}, - {file = "ruff-0.15.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9cae0f92bd5700d1213188b31cd3bdd2b315361296d10b96b8e2337d3d11f53e"}, - {file = "ruff-0.15.12-py3-none-win32.whl", hash = "sha256:d0185894e038d7043ba8fd6aee7499ece6462dc0ea9f1e260c7451807c714c20"}, - {file = "ruff-0.15.12-py3-none-win_amd64.whl", hash = "sha256:c87a162d61ab3adca47c03f7f717c68672edec7d1b5499e652331780fe74950d"}, - {file = "ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f"}, - {file = "ruff-0.15.12.tar.gz", hash = "sha256:ecea26adb26b4232c0c2ca19ccbc0083a68344180bba2a600605538ce51a40a6"}, + {file = "ruff-0.15.22-py3-none-linux_armv6l.whl", hash = "sha256:44423e73493737f5e7c5b41d475483898ff37afcdae38bc3da5085e29af1c2d8"}, + {file = "ruff-0.15.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b82c6482946e9eda7ff2e091d25b8bad3f718684e1916d41bd56873cee05b697"}, + {file = "ruff-0.15.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:11c1c715af53a09f714e011106bffc419751ec8232fcb5da42173284ea3fec6f"}, + {file = "ruff-0.15.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742a29cf29bddb7c8327895d6a10e0e6c5b38a96dd407af9b5d0857f809c0576"}, + {file = "ruff-0.15.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72af58b951b0ae395935ae79763dc349bc0eb706319d28f7a33ad2cfb3cfc178"}, + {file = "ruff-0.15.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62d425005c1835eb24e2ee4161cb90e8db263415f4a71c8c72c33abaa6c0c224"}, + {file = "ruff-0.15.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8b9b3f8779a4f08c969defc3c8c35abffaa757e601ed5ae66d6d1db6519969a"}, + {file = "ruff-0.15.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e0dd1b2e4d3d585f897a0d137cbf4eaf6223bef4e8ce34d6bb12556c5f9249e"}, + {file = "ruff-0.15.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365523eb91d9224e1bcb03b022fbf0facb8f9e23792a2c53d9d4b3924bdbdebb"}, + {file = "ruff-0.15.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:fabfd168afdf29fee5be98b831efa9683c94d7c5a3b58b9ce5a2e38444589a74"}, + {file = "ruff-0.15.22-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:225dbf095a87f1d9f90f5fd7924d2613ee452a75a4308c63a8f50f761787aa7c"}, + {file = "ruff-0.15.22-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1877d63b9d24ed278744f1523fd11b85540566d54641f97c566d7d9dc5ca5296"}, + {file = "ruff-0.15.22-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a1606c510bd7215680d32efab38965f7cdec3ef69f5170a3f4791404ffdd5262"}, + {file = "ruff-0.15.22-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:630479b18625f5ffc373f77603a22a9f8ac0acd7ff0501178b5db28ec71e9c64"}, + {file = "ruff-0.15.22-py3-none-win32.whl", hash = "sha256:e5ba0e4a13fd14abbed2a77b517a3911290c6c6c59ef67784328d1668fab76cf"}, + {file = "ruff-0.15.22-py3-none-win_amd64.whl", hash = "sha256:9be63ba1eb936acd2d1342fb8337c356353706fce233b2a15a09a97037e6acde"}, + {file = "ruff-0.15.22-py3-none-win_arm64.whl", hash = "sha256:e1168075b72158510839f250027659cdd78476f40507dd517892304c41318661"}, + {file = "ruff-0.15.22.tar.gz", hash = "sha256:3f15175b1fb580126f58285a5dae6b2ea89000136d980c64499211f116b54809"}, ] [[package]] name = "selenium" -version = "4.43.0" +version = "4.46.0" description = "Official Python bindings for Selenium WebDriver" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "selenium-4.43.0-py3-none-any.whl", hash = "sha256:4f97639055dcfa9eadf8ccf549ba7b0e49c655d4e2bde19b9a44e916b754e769"}, - {file = "selenium-4.43.0.tar.gz", hash = "sha256:bada5c08a989f812728a4b5bea884d8e91894e939a441cc3a025201ce718581e"}, + {file = "selenium-4.46.0-py3-none-any.whl", hash = "sha256:f03e864770a21ab32009961c9d015cb2c6275eba45c926c272e02d90af423aad"}, + {file = "selenium-4.46.0.tar.gz", hash = "sha256:54f7e1a4df5f7508ac8c38ce2ea584db1b27083dd79962b22524219219df5cbe"}, ] [package.dependencies] -certifi = ">=2026.1.4" +certifi = ">=2026.2.25" trio = ">=0.31.0,<1.0" trio-websocket = ">=0.12.2,<1.0" typing_extensions = ">=4.15.0,<5.0" @@ -6228,37 +5977,24 @@ websocket-client = ">=1.8.0,<2.0" [[package]] name = "setuptools" -version = "82.0.1" +version = "83.0.0" description = "Most extensible Python build backend with support for C/C++ extension modules" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb"}, - {file = "setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9"}, + {file = "setuptools-83.0.0-py3-none-any.whl", hash = "sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3"}, + {file = "setuptools-83.0.0.tar.gz", hash = "sha256:025bccbbf0fa05b6192bc64ae1e7b16e001fd6d6d4d5de03c97b1c1ade523bef"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.13.0) ; sys_platform != \"cygwin\""] +check = ["pytest-checkdocs (>=2.14)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.13.0) ; sys_platform != \"cygwin\""] core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -enabler = ["pytest-enabler (>=2.2)"] +enabler = ["pytest-enabler (>=3.4)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.18.*)", "pytest-mypy"] - -[[package]] -name = "shellingham" -version = "1.5.4" -description = "Tool to Detect Surrounding Shell" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version < \"3.14\"" -files = [ - {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, - {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, -] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.18.*)", "pytest-mypy (>=1.0.1) ; platform_python_implementation != \"PyPy\""] [[package]] name = "six" @@ -6298,14 +6034,14 @@ files = [ [[package]] name = "soupsieve" -version = "2.8.4" +version = "2.9.1" description = "A modern CSS selector implementation for Beautiful Soup." optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "soupsieve-2.8.4-py3-none-any.whl", hash = "sha256:e7e6b0769c8f51ed59acab6e994b00621096cfb1c640a7509295987388fbaf65"}, - {file = "soupsieve-2.8.4.tar.gz", hash = "sha256:e121fd02e975c695e4e9e8774a5ee35d74714b59307868dcc5319ad2d9e3328e"}, + {file = "soupsieve-2.9.1-py3-none-any.whl", hash = "sha256:4f4477399246b7a0c720a88ca2454b11cd6bb9ae4c9d170140786e916776c14c"}, + {file = "soupsieve-2.9.1.tar.gz", hash = "sha256:c33e6605bbc71dd628b00c632d58ae607c22bade247e52553928f83bbb75b4ba"}, ] [[package]] @@ -6326,14 +6062,14 @@ doc = ["sphinx"] [[package]] name = "sse-starlette" -version = "3.4.1" +version = "3.4.6" description = "SSE plugin for Starlette" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "sse_starlette-3.4.1-py3-none-any.whl", hash = "sha256:6b43cf21f1d574d582a6e1b0cfbde1c94dc86a32a701a7168c99c4475c6bd1d0"}, - {file = "sse_starlette-3.4.1.tar.gz", hash = "sha256:f780bebcf6c8997fe514e3bd8e8c648d8284976b391c8bed0bcb1f611632b555"}, + {file = "sse_starlette-3.4.6-py3-none-any.whl", hash = "sha256:56217ab4c9a9f9c5db7b21e08732d3e7c2b807f45231ad23de0551a24c4a41f6"}, + {file = "sse_starlette-3.4.6.tar.gz", hash = "sha256:725f8a1bd6d26ae1b2c9610c0ef5065dfdd496f3988d28adcf8c4b49dc25c627"}, ] [package.dependencies] @@ -6368,20 +6104,19 @@ full = ["httpx (>=0.27.0,<0.29.0)", "httpx2 (>=2.0.0)", "itsdangerous", "jinja2" [[package]] name = "stone" -version = "3.3.1" +version = "3.5.3" description = "Stone is an interface description language (IDL) for APIs." optional = false -python-versions = "*" +python-versions = ">=3.11" groups = ["main"] files = [ - {file = "stone-3.3.1-py2-none-any.whl", hash = "sha256:cd2f7f9056fc39b16c8fd46a26971dc5ccd30b5c2c246566cd2c0dd27ff96609"}, - {file = "stone-3.3.1-py3-none-any.whl", hash = "sha256:e15866fad249c11a963cce3bdbed37758f2e88c8ff4898616bc0caeb1e216047"}, - {file = "stone-3.3.1.tar.gz", hash = "sha256:4ef0397512f609757975f7ec09b35639d72ba7e3e17ce4ddf399578346b4cb50"}, + {file = "stone-3.5.3-py3-none-any.whl", hash = "sha256:5d78bd0b60692756b44758d876d74e4ed2ed938e29aa62646e3cbc247844027b"}, + {file = "stone-3.5.3.tar.gz", hash = "sha256:d0d99f14d154452e71b3e2752efdbbb1769e4fecbc1291b1dfd1a046f7b6a1cb"}, ] [package.dependencies] -ply = ">=3.4" -six = ">=1.12.0" +Jinja2 = ">=3.0.3" +packaging = ">=21.0" [[package]] name = "tabulate" @@ -6431,112 +6166,105 @@ rapidfuzz = ">=3.0.0,<4.0.0" [[package]] name = "tiktoken" -version = "0.12.0" +version = "0.13.0" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = false python-versions = ">=3.9" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "tiktoken-0.12.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3de02f5a491cfd179aec916eddb70331814bd6bf764075d39e21d5862e533970"}, - {file = "tiktoken-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6cfb6d9b7b54d20af21a912bfe63a2727d9cfa8fbda642fd8322c70340aad16"}, - {file = "tiktoken-0.12.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:cde24cdb1b8a08368f709124f15b36ab5524aac5fa830cc3fdce9c03d4fb8030"}, - {file = "tiktoken-0.12.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6de0da39f605992649b9cfa6f84071e3f9ef2cec458d08c5feb1b6f0ff62e134"}, - {file = "tiktoken-0.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6faa0534e0eefbcafaccb75927a4a380463a2eaa7e26000f0173b920e98b720a"}, - {file = "tiktoken-0.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:82991e04fc860afb933efb63957affc7ad54f83e2216fe7d319007dab1ba5892"}, - {file = "tiktoken-0.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:6fb2995b487c2e31acf0a9e17647e3b242235a20832642bb7a9d1a181c0c1bb1"}, - {file = "tiktoken-0.12.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e227c7f96925003487c33b1b32265fad2fbcec2b7cf4817afb76d416f40f6bb"}, - {file = "tiktoken-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c06cf0fcc24c2cb2adb5e185c7082a82cba29c17575e828518c2f11a01f445aa"}, - {file = "tiktoken-0.12.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:f18f249b041851954217e9fd8e5c00b024ab2315ffda5ed77665a05fa91f42dc"}, - {file = "tiktoken-0.12.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:47a5bc270b8c3db00bb46ece01ef34ad050e364b51d406b6f9730b64ac28eded"}, - {file = "tiktoken-0.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:508fa71810c0efdcd1b898fda574889ee62852989f7c1667414736bcb2b9a4bd"}, - {file = "tiktoken-0.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1af81a6c44f008cba48494089dd98cccb8b313f55e961a52f5b222d1e507967"}, - {file = "tiktoken-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:3e68e3e593637b53e56f7237be560f7a394451cb8c11079755e80ae64b9e6def"}, - {file = "tiktoken-0.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b97f74aca0d78a1ff21b8cd9e9925714c15a9236d6ceacf5c7327c117e6e21e8"}, - {file = "tiktoken-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b90f5ad190a4bb7c3eb30c5fa32e1e182ca1ca79f05e49b448438c3e225a49b"}, - {file = "tiktoken-0.12.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:65b26c7a780e2139e73acc193e5c63ac754021f160df919add909c1492c0fb37"}, - {file = "tiktoken-0.12.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:edde1ec917dfd21c1f2f8046b86348b0f54a2c0547f68149d8600859598769ad"}, - {file = "tiktoken-0.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:35a2f8ddd3824608b3d650a000c1ef71f730d0c56486845705a8248da00f9fe5"}, - {file = "tiktoken-0.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83d16643edb7fa2c99eff2ab7733508aae1eebb03d5dfc46f5565862810f24e3"}, - {file = "tiktoken-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffc5288f34a8bc02e1ea7047b8d041104791d2ddbf42d1e5fa07822cbffe16bd"}, - {file = "tiktoken-0.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:775c2c55de2310cc1bc9a3ad8826761cbdc87770e586fd7b6da7d4589e13dab3"}, - {file = "tiktoken-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a01b12f69052fbe4b080a2cfb867c4de12c704b56178edf1d1d7b273561db160"}, - {file = "tiktoken-0.12.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:01d99484dc93b129cd0964f9d34eee953f2737301f18b3c7257bf368d7615baa"}, - {file = "tiktoken-0.12.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:4a1a4fcd021f022bfc81904a911d3df0f6543b9e7627b51411da75ff2fe7a1be"}, - {file = "tiktoken-0.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:981a81e39812d57031efdc9ec59fa32b2a5a5524d20d4776574c4b4bd2e9014a"}, - {file = "tiktoken-0.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9baf52f84a3f42eef3ff4e754a0db79a13a27921b457ca9832cf944c6be4f8f3"}, - {file = "tiktoken-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b8a0cd0c789a61f31bf44851defbd609e8dd1e2c8589c614cc1060940ef1f697"}, - {file = "tiktoken-0.12.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d5f89ea5680066b68bcb797ae85219c72916c922ef0fcdd3480c7d2315ffff16"}, - {file = "tiktoken-0.12.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b4e7ed1c6a7a8a60a3230965bdedba8cc58f68926b835e519341413370e0399a"}, - {file = "tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:fc530a28591a2d74bce821d10b418b26a094bf33839e69042a6e86ddb7a7fb27"}, - {file = "tiktoken-0.12.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:06a9f4f49884139013b138920a4c393aa6556b2f8f536345f11819389c703ebb"}, - {file = "tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:04f0e6a985d95913cabc96a741c5ffec525a2c72e9df086ff17ebe35985c800e"}, - {file = "tiktoken-0.12.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ee8f9ae00c41770b5f9b0bb1235474768884ae157de3beb5439ca0fd70f3e25"}, - {file = "tiktoken-0.12.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc2dd125a62cb2b3d858484d6c614d136b5b848976794edfb63688d539b8b93f"}, - {file = "tiktoken-0.12.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a90388128df3b3abeb2bfd1895b0681412a8d7dc644142519e6f0a97c2111646"}, - {file = "tiktoken-0.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:da900aa0ad52247d8794e307d6446bd3cdea8e192769b56276695d34d2c9aa88"}, - {file = "tiktoken-0.12.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:285ba9d73ea0d6171e7f9407039a290ca77efcdb026be7769dccc01d2c8d7fff"}, - {file = "tiktoken-0.12.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:d186a5c60c6a0213f04a7a802264083dea1bbde92a2d4c7069e1a56630aef830"}, - {file = "tiktoken-0.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:604831189bd05480f2b885ecd2d1986dc7686f609de48208ebbbddeea071fc0b"}, - {file = "tiktoken-0.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8f317e8530bb3a222547b85a58583238c8f74fd7a7408305f9f63246d1a0958b"}, - {file = "tiktoken-0.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:399c3dd672a6406719d84442299a490420b458c44d3ae65516302a99675888f3"}, - {file = "tiktoken-0.12.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2c714c72bc00a38ca969dae79e8266ddec999c7ceccd603cc4f0d04ccd76365"}, - {file = "tiktoken-0.12.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cbb9a3ba275165a2cb0f9a83f5d7025afe6b9d0ab01a22b50f0e74fee2ad253e"}, - {file = "tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:dfdfaa5ffff8993a3af94d1125870b1d27aed7cb97aa7eb8c1cefdbc87dbee63"}, - {file = "tiktoken-0.12.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:584c3ad3d0c74f5269906eb8a659c8bfc6144a52895d9261cdaf90a0ae5f4de0"}, - {file = "tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:54c891b416a0e36b8e2045b12b33dd66fb34a4fe7965565f1b482da50da3e86a"}, - {file = "tiktoken-0.12.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5edb8743b88d5be814b1a8a8854494719080c28faaa1ccbef02e87354fe71ef0"}, - {file = "tiktoken-0.12.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f61c0aea5565ac82e2ec50a05e02a6c44734e91b51c10510b084ea1b8e633a71"}, - {file = "tiktoken-0.12.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:d51d75a5bffbf26f86554d28e78bfb921eae998edc2675650fd04c7e1f0cdc1e"}, - {file = "tiktoken-0.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:09eb4eae62ae7e4c62364d9ec3a57c62eea707ac9a2b2c5d6bd05de6724ea179"}, - {file = "tiktoken-0.12.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:df37684ace87d10895acb44b7f447d4700349b12197a526da0d4a4149fde074c"}, - {file = "tiktoken-0.12.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:4c9614597ac94bb294544345ad8cf30dac2129c05e2db8dc53e082f355857af7"}, - {file = "tiktoken-0.12.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:20cf97135c9a50de0b157879c3c4accbb29116bcf001283d26e073ff3b345946"}, - {file = "tiktoken-0.12.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:15d875454bbaa3728be39880ddd11a5a2a9e548c29418b41e8fd8a767172b5ec"}, - {file = "tiktoken-0.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cff3688ba3c639ebe816f8d58ffbbb0aa7433e23e08ab1cade5d175fc973fb3"}, - {file = "tiktoken-0.12.0.tar.gz", hash = "sha256:b18ba7ee2b093863978fcb14f74b3707cdc8d4d4d3836853ce7ec60772139931"}, -] - -[package.dependencies] -regex = ">=2022.1.18" -requests = ">=2.26.0" + {file = "tiktoken-0.13.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:47b1df8d73390a24f94980c75158cdd5c56d256f16d55f30cb49c230caba9ba4"}, + {file = "tiktoken-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7d40c6c5aab171dcd6eb8455bc567bde404bb9def60cdb8c1299cc782b242bb9"}, + {file = "tiktoken-0.13.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:9b842981fa91accdffd48ff6408a977b7a91c3fbda55d353c3c68114d5c9d69e"}, + {file = "tiktoken-0.13.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ed5a30027cb4d8c7ca8b273d4766f3db3cf58fad9e9f3b1a68a351ffb54873d5"}, + {file = "tiktoken-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7ab10f4a21c2999846940113f6dbd72e0fa06a24119feddd74cc47e85818e06d"}, + {file = "tiktoken-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a2937ad042d49d50eac6e1ba07c5661d4bd3942a5b1e0c0d08475c4df83676e1"}, + {file = "tiktoken-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:44733b99bfd72b590cd0936b1c01b3b4dd73122db2d544bc1ceeb18a7678c910"}, + {file = "tiktoken-0.13.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7bfe1849caa65d1e1d9871817170ec497bbb7984e182012e1bdce72f66608cdb"}, + {file = "tiktoken-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:91c180fe255bd5a86d8316210d2833a1d4d33d026cd86a67812f4773743c8d26"}, + {file = "tiktoken-0.13.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:059c8ecf554eb5b41e6e054ba467b871b03277d267dee7244380aca4359747d4"}, + {file = "tiktoken-0.13.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:36217497eaffc158607a3b26f065300db2aefd43b115263f3b9688ce38146173"}, + {file = "tiktoken-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:303f7d91b4fce3baddbcde05c139091d4caa5026ac7214c1dc7ff7a71ee429ff"}, + {file = "tiktoken-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5d48843bee149630eb735a99e1f4a85b47308d21868ea63163f6e87768d3cfed"}, + {file = "tiktoken-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:fc1c44cd37b43fc46bae593129164f4f281e82ea116b57a85aa81bda57eafc94"}, + {file = "tiktoken-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:32ac870a806cfb260a02d0cb70426aef02e038297f8ad50df5040bb5af360791"}, + {file = "tiktoken-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d9980f11429ed2d737c463bb1fb78cf330caa026adf002f714aced7849a687b"}, + {file = "tiktoken-0.13.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3f277ebea5edd7b8bf03c6f9431e1d67d517530115572b2dc1d465326e8f88c7"}, + {file = "tiktoken-0.13.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:a116178fa7e1b4065bff05214360373a65cac22f965be7b3f73d00a0dbfe7649"}, + {file = "tiktoken-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c397ddda233208345b01bd30f2fca79ff730e55731d0108a603f9bc57f6af3b"}, + {file = "tiktoken-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:95097e4f89b06403976e498abf61a0ee73a7497e73fb599cb211d8197a054d91"}, + {file = "tiktoken-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:8f2d16e7a7c783ad81f36e457d046d1f1c8af70b22aec8a13238efe531977c41"}, + {file = "tiktoken-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5df5d1507bd245f1ccad4a074698240021239e455eb0bb4ced4e3d7181872154"}, + {file = "tiktoken-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8fe806a50664e83a6ffd56cbd1e4f5dcc6cd32a3e7538f70dc38b1a271384545"}, + {file = "tiktoken-0.13.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:125bc05005e747f993a83dc67934249932d6e4209854452cd4c0b1d53fba3ba2"}, + {file = "tiktoken-0.13.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5e6358911cab4adee6712da27d65573496a4f68cf8a2b5fca6a4ad10fc5748cf"}, + {file = "tiktoken-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:975cbd78d085d75d26b59660e262736dcaed1e35f8f142cd6291025c01d25486"}, + {file = "tiktoken-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:75ab9bc99fa020a4c283424590ecd7f3afd70c1c281cb3fa3192a6c3af9f9615"}, + {file = "tiktoken-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:6b1615f0ff71953d19729ceb18865429c185b0a23c5353f1bbca34a394bf60f7"}, + {file = "tiktoken-0.13.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6eb4a5bfbc6426938026b1a334e898ac53541360d62d8c689870160cc80abd67"}, + {file = "tiktoken-0.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:43cee3e5400573b2046fbf092cc7a5bc30164f9e4c95ce20714da929df48737a"}, + {file = "tiktoken-0.13.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:7de52e3f566d19b3b11bd37eea552c6c305ad74081f736882bd44d148ed4c48d"}, + {file = "tiktoken-0.13.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:51384448aa508e4df84c0f7c1dc3211c7f7b8096325660ee5fc82f3e11b381ce"}, + {file = "tiktoken-0.13.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e28157350f7ebf35008dd8e9e0fdb621f976e4230c881099c85e8cf07eaa50e2"}, + {file = "tiktoken-0.13.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:165cf1820ea4a354985c2490a5205d4cc74661c934aca79dd0368232fff94e0f"}, + {file = "tiktoken-0.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6c43a675ca14f6f2749ba7f12075d37456015a24b859f2517b9beb4ef30807ec"}, + {file = "tiktoken-0.13.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaaaef47c2406277181d2086484c317bf7fc433e2d5d03ff94f56b0dcec87471"}, + {file = "tiktoken-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ca8b310bd93b3772cb1b7922d915446864860f562bdfe4825c63a0aed3fb28cd"}, + {file = "tiktoken-0.13.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:32e0c12305105002c047b3bb1070b0dd9a73b0cb3b2856a8972b810e7a4f5881"}, + {file = "tiktoken-0.13.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:5ba5fd62507a932d1241346179e3b39bc7bf7408f03c272652d93b3bedf5db24"}, + {file = "tiktoken-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d108bc2d470fc53c8ecd24f2c0fd2b5f98c33e87cdb6aa2e9b8c5dced703d273"}, + {file = "tiktoken-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cb99cb5127449f58d0a2d5f5ccfb390d8dbdfd919c221246caaee29d8725ed51"}, + {file = "tiktoken-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:115c4f26ffa11caac8b54eea35c2ad38c612c20a48d35dd15d70a02ac6f51f58"}, + {file = "tiktoken-0.13.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:472527e9132952f2fbf77cd290658bacf003d4d5a3fabc18e5fbd407cbae4d9b"}, + {file = "tiktoken-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4e2f67d27c9626cdd25fe33d9313c5cdb3d8d82da646b68d6eb8e7e9c20e6448"}, + {file = "tiktoken-0.13.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:2b920b35805cd64585a37c3dc7ce65fba4d2d36016be01e1d7942482ca29093a"}, + {file = "tiktoken-0.13.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:493af3aa28a4aaf2e3d2600a2ee717252c9bf5ab38fff94eb5a02db5ab77e5ad"}, + {file = "tiktoken-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6644c9c2b5cf3916f5a3641d7d12fdb3f006a7b3d9ff6acdaec44e29ab1ff91e"}, + {file = "tiktoken-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5cb65b60b9408563676d874a3a4ee573370066f0dc4e29d84e82e989c6517424"}, + {file = "tiktoken-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:85b78cc3a2c3d48723ca751fa981f1fedccd54194ca0471b957364353a898b07"}, + {file = "tiktoken-0.13.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:35e1ea1e0631c04f551297284a1ab7e1f65a3c55a9a48728d5e0f66b4527c04a"}, + {file = "tiktoken-0.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2a3b536c55802fe42f4b4644d2be4f04bf788506b48de0a0a658cb58f8bce232"}, + {file = "tiktoken-0.13.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:b8ac2d6420ff05841a89ba5205c6d45f56c4f6843454f3c884b7eb1a2a8dddb2"}, + {file = "tiktoken-0.13.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:477c9a38e20d0ed248090509acf1e839ad3967a4f00b4b0f958210049f656dee"}, + {file = "tiktoken-0.13.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:da86f8c96ac1c235d7a3b3eebff1eacfdbcfb8ad792706943268d4d2938fbafe"}, + {file = "tiktoken-0.13.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9b8858b29804b3a0add25ce9e62fb00f89f621dc754d75d03ca419d17e8ddf67"}, + {file = "tiktoken-0.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:b967dfb9d0adf9a631953b1b40717684f04478270fc51bbccdd2f838d67a2f00"}, + {file = "tiktoken-0.13.0.tar.gz", hash = "sha256:c9435714c3a84c2319499de9a300c0e604449dd0799ff246458b3bb6a7f433c1"}, +] + +[package.dependencies] +regex = "*" +requests = "*" [package.extras] -blobfile = ["blobfile (>=2)"] +blobfile = ["blobfile (>=3)"] [[package]] name = "tokenizers" -version = "0.22.2" +version = "0.23.1" description = "" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "tokenizers-0.22.2-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:544dd704ae7238755d790de45ba8da072e9af3eea688f698b137915ae959281c"}, - {file = "tokenizers-0.22.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1e418a55456beedca4621dbab65a318981467a2b188e982a23e117f115ce5001"}, - {file = "tokenizers-0.22.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2249487018adec45d6e3554c71d46eb39fa8ea67156c640f7513eb26f318cec7"}, - {file = "tokenizers-0.22.2-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b85325d0815e86e0bac263506dd114578953b7b53d7de09a6485e4a160a7dd"}, - {file = "tokenizers-0.22.2-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfb88f22a209ff7b40a576d5324bf8286b519d7358663db21d6246fb17eea2d5"}, - {file = "tokenizers-0.22.2-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c774b1276f71e1ef716e5486f21e76333464f47bece56bbd554485982a9e03e"}, - {file = "tokenizers-0.22.2-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b"}, - {file = "tokenizers-0.22.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:369cc9fc8cc10cb24143873a0d95438bb8ee257bb80c71989e3ee290e8d72c67"}, - {file = "tokenizers-0.22.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:29c30b83d8dcd061078b05ae0cb94d3c710555fbb44861139f9f83dcca3dc3e4"}, - {file = "tokenizers-0.22.2-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:37ae80a28c1d3265bb1f22464c856bd23c02a05bb211e56d0c5301a435be6c1a"}, - {file = "tokenizers-0.22.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:791135ee325f2336f498590eb2f11dc5c295232f288e75c99a36c5dbce63088a"}, - {file = "tokenizers-0.22.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:38337540fbbddff8e999d59970f3c6f35a82de10053206a7562f1ea02d046fa5"}, - {file = "tokenizers-0.22.2-cp39-abi3-win32.whl", hash = "sha256:a6bf3f88c554a2b653af81f3204491c818ae2ac6fbc09e76ef4773351292bc92"}, - {file = "tokenizers-0.22.2-cp39-abi3-win_amd64.whl", hash = "sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48"}, - {file = "tokenizers-0.22.2-cp39-abi3-win_arm64.whl", hash = "sha256:9ce725d22864a1e965217204946f830c37876eee3b2ba6fc6255e8e903d5fcbc"}, - {file = "tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:753d47ebd4542742ef9261d9da92cd545b2cacbb48349a1225466745bb866ec4"}, - {file = "tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e10bf9113d209be7cd046d40fbabbaf3278ff6d18eb4da4c500443185dc1896c"}, - {file = "tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64d94e84f6660764e64e7e0b22baa72f6cd942279fdbb21d46abd70d179f0195"}, - {file = "tokenizers-0.22.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f01a9c019878532f98927d2bacb79bbb404b43d3437455522a00a30718cdedb5"}, - {file = "tokenizers-0.22.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:319f659ee992222f04e58f84cbf407cfa66a65fe3a8de44e8ad2bc53e7d99012"}, - {file = "tokenizers-0.22.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1e50f8554d504f617d9e9d6e4c2c2884a12b388a97c5c77f0bc6cf4cd032feee"}, - {file = "tokenizers-0.22.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a62ba2c5faa2dd175aaeed7b15abf18d20266189fb3406c5d0550dd34dd5f37"}, - {file = "tokenizers-0.22.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:143b999bdc46d10febb15cbffb4207ddd1f410e2c755857b5a0797961bbdc113"}, - {file = "tokenizers-0.22.2.tar.gz", hash = "sha256:473b83b915e547aa366d1eee11806deaf419e17be16310ac0a14077f1e28f917"}, + {file = "tokenizers-0.23.1-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e03d6ffcbe0d56ee9c1ccd070e70a13fa750727c0277e138152acbc0252c2224"}, + {file = "tokenizers-0.23.1-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:e0948bbb1ac1d7cdfc9fb6d62c596e3b7550036ad60ecd654a66ad273326324e"}, + {file = "tokenizers-0.23.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bf13402aff9bc533c89cb849ec3b412dc3fbeacc9744840e423d7bf3f7dc0e3"}, + {file = "tokenizers-0.23.1-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f836ca703b89ae07919a309f9651f7a88fd5a33d5f718ba5ad0870ec0256bad6"}, + {file = "tokenizers-0.23.1-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae848657742035523fdf261773630cb819a26995fcd3d9ecae0c1daf6e5a4959"}, + {file = "tokenizers-0.23.1-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53b09e85775d5187941e7bab30e941b4134ab4a7dd8c68e783d231fb7ca27c51"}, + {file = "tokenizers-0.23.1-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea5a0ce170074329faaa8ea3f6400ecde604b6678192688533af80980daae71a"}, + {file = "tokenizers-0.23.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5075b405006415ea148a992d093699c66eb01952bf59f4d5727089a98bda45a4"}, + {file = "tokenizers-0.23.1-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:56f3a77de629917652f876294dc9fe6bad4a0c43bc229dc72e59bb23a0f4729a"}, + {file = "tokenizers-0.23.1-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9d10a6d957ef01896dc274e890eee27d41bd0e74ef31e60616f0fc311345184e"}, + {file = "tokenizers-0.23.1-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1974288a609c343774f1b897c8b482c791ab17b75ab5c8c2b1737565c1d82288"}, + {file = "tokenizers-0.23.1-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:120468fb4c24faf0543c835a4fabafa4deb3f20a035c9b6e83d0b553a97615d4"}, + {file = "tokenizers-0.23.1-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e3d8f40ea6268047de7046906326abed5134f27d4e8447b23763afe5808c8a96"}, + {file = "tokenizers-0.23.1-cp310-abi3-win32.whl", hash = "sha256:93120a930b919416da7cd10a2f606ac9919cc69cacae7980fa2140e277660948"}, + {file = "tokenizers-0.23.1-cp310-abi3-win_amd64.whl", hash = "sha256:e7bfaf995c1bdbbd21d13539decb6650967013759318627d85daeb7881af16b7"}, + {file = "tokenizers-0.23.1-cp310-abi3-win_arm64.whl", hash = "sha256:a26197957d8e4425dfba746315f3c425ea00cfa8367c5fbc4ec73447893dcea9"}, + {file = "tokenizers-0.23.1.tar.gz", hash = "sha256:1feeeadf865a7915adc25445dea30e9933e593c31bb96c277cee36de227c8bfa"}, ] [package.dependencies] @@ -6631,26 +6359,26 @@ files = [ [[package]] name = "tomlkit" -version = "0.15.0" +version = "0.15.1" description = "Style preserving TOML library" optional = false python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "tomlkit-0.15.0-py3-none-any.whl", hash = "sha256:4dbc8f0fc024412b57ced8757ac7461305126a648ff8c2c807fcb8e133a78738"}, - {file = "tomlkit-0.15.0.tar.gz", hash = "sha256:7d1a9ecba3086638211b13814ea79c90dd54dd11993564376f3aa92271f5c7a3"}, + {file = "tomlkit-0.15.1-py3-none-any.whl", hash = "sha256:177a05aece5a8ca5266fd3c448abb47b8d352f09d477d3ca8332db4d89b24304"}, + {file = "tomlkit-0.15.1.tar.gz", hash = "sha256:e25bbf38843005246210a12982776f27f99cb9be67160e14434d0c0d21ee1e97"}, ] [[package]] name = "tox" -version = "4.53.1" +version = "4.58.0" description = "tox is a generic virtualenv management and test command line tool" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "tox-4.53.1-py3-none-any.whl", hash = "sha256:4a9948607e976a337c22d64a1b4fafd486125e82f00ab6ce32fa6cacc23f48b1"}, - {file = "tox-4.53.1.tar.gz", hash = "sha256:7be9805ed4a34242510c7acc9a7e3a01a35942e08f31f8bd69067c3a37130afc"}, + {file = "tox-4.58.0-py3-none-any.whl", hash = "sha256:dcae21f5f015f3a67658e35644cce0d1aa0dedcd06f3927f95d84e1717f6cea5"}, + {file = "tox-4.58.0.tar.gz", hash = "sha256:ab0b126a04dd56bc18e6d216386db09335247f2289b54cf534deb5c4ae3a8d2e"}, ] [package.dependencies] @@ -6661,34 +6389,35 @@ packaging = ">=26" platformdirs = ">=4.9.4" pluggy = ">=1.6" pyproject-api = ">=1.10" -python-discovery = ">=1.2.2" +python-discovery = ">=1.4.4" tomli-w = ">=1.2" virtualenv = ">=21.1" [package.extras] completion = ["argcomplete (>=3.6.3)"] +testing = ["devpi-process (>=1.1.1)", "pytest (>=9.0.2)", "pytest-mock (>=3.15.1)"] [[package]] name = "tqdm" -version = "4.67.3" +version = "4.69.1" description = "Fast, Extensible Progress Meter" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["main"] +markers = "python_version < \"3.14\"" files = [ - {file = "tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf"}, - {file = "tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb"}, + {file = "tqdm-4.69.1-py3-none-any.whl", hash = "sha256:0a654b96f7a2660cceb615b56f307ec2bef96c515409014a429a561981ab52b4"}, + {file = "tqdm-4.69.1.tar.gz", hash = "sha256:2be21080a0ce17e902c2f1baeb6a74bf551b67bbdfa4bc0109fad471d0b4cb0d"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] -dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"] -discord = ["requests"] +discord = ["envwrap", "requests"] notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] +slack = ["envwrap", "slack-sdk"] +telegram = ["envwrap", "requests"] [[package]] name = "trio" @@ -6727,35 +6456,16 @@ outcome = ">=1.2.0" trio = ">=0.11" wsproto = ">=0.14" -[[package]] -name = "typer" -version = "0.23.1" -description = "Typer, build great CLIs. Easy to code. Based on Python type hints." -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version < \"3.14\"" -files = [ - {file = "typer-0.23.1-py3-none-any.whl", hash = "sha256:3291ad0d3c701cbf522012faccfbb29352ff16ad262db2139e6b01f15781f14e"}, - {file = "typer-0.23.1.tar.gz", hash = "sha256:2070374e4d31c83e7b61362fd859aa683576432fd5b026b060ad6b4cd3b86134"}, -] - -[package.dependencies] -annotated-doc = ">=0.0.2" -click = ">=8.0.0" -rich = ">=10.11.0" -shellingham = ">=1.3.0" - [[package]] name = "types-httplib2" -version = "0.31.2.20260408" +version = "0.32.0.20260720" description = "Typing stubs for httplib2" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_httplib2-0.31.2.20260408-py3-none-any.whl", hash = "sha256:a6ef6deea469e71fbde4226c2a79c5ed8f40f201171d9bcd2ba20752dbf3766e"}, - {file = "types_httplib2-0.31.2.20260408.tar.gz", hash = "sha256:ebf7ba1b5910500762df8bbafcad8f6e5813403442dc0439d86788d81327f1fe"}, + {file = "types_httplib2-0.32.0.20260720-py3-none-any.whl", hash = "sha256:c8e838557fccd39bb08569839c7e625489c5b2db1c89ab54b6a3b808b9e9b392"}, + {file = "types_httplib2-0.32.0.20260720.tar.gz", hash = "sha256:fdf42301174bccd6cede13dcffe130753f5c32c64b0a2b681a011504ffe6d1eb"}, ] [[package]] @@ -6775,62 +6485,62 @@ referencing = "*" [[package]] name = "types-python-dateutil" -version = "2.9.0.20260408" +version = "2.9.0.20260716" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_python_dateutil-2.9.0.20260408-py3-none-any.whl", hash = "sha256:473139d514a71c9d1fbd8bb328974bedcb1cc3dba57aad04ffa4157f483c216f"}, - {file = "types_python_dateutil-2.9.0.20260408.tar.gz", hash = "sha256:8b056ec01568674235f64ecbcef928972a5fac412f5aab09c516dfa2acfbb582"}, + {file = "types_python_dateutil-2.9.0.20260716-py3-none-any.whl", hash = "sha256:1ae41d51a5c5f6bbeeb7f1f34df7086d55ff1605cf88d2ed71a7a276e1a7794e"}, + {file = "types_python_dateutil-2.9.0.20260716.tar.gz", hash = "sha256:1d55d1c3024bdb4861bb6a6622c9ec800c433d87bdc5b16fb84cdd0eed4ef2cb"}, ] [[package]] name = "types-pytz" -version = "2026.1.1.20260408" +version = "2026.3.1.20260727" description = "Typing stubs for pytz" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_pytz-2026.1.1.20260408-py3-none-any.whl", hash = "sha256:c7e4dec76221fb7d0c97b91ad8561d689bebe39b6bcb7b728387e7ffd8cde788"}, - {file = "types_pytz-2026.1.1.20260408.tar.gz", hash = "sha256:89b6a34b9198ea2a4b98a9d15cbca987053f52a105fd44f7ce3789cae4349408"}, + {file = "types_pytz-2026.3.1.20260727-py3-none-any.whl", hash = "sha256:42ac44e83645bfceb46597342c8fb8ec028a1407e2feae9c5c539986eab6b57a"}, + {file = "types_pytz-2026.3.1.20260727.tar.gz", hash = "sha256:4364075b6867dd15b210bb8c1d29727d609917129b45600defe1d4b3eda5ecb9"}, ] [[package]] name = "types-pyyaml" -version = "6.0.12.20260408" +version = "6.0.12.20260724" description = "Typing stubs for PyYAML" optional = false python-versions = ">=3.10" groups = ["main", "dev"] files = [ - {file = "types_pyyaml-6.0.12.20260408-py3-none-any.whl", hash = "sha256:fbc42037d12159d9c801ebfcc79ebd28335a7c13b08a4cfbc6916df78fee9384"}, - {file = "types_pyyaml-6.0.12.20260408.tar.gz", hash = "sha256:92a73f2b8d7f39ef392a38131f76b970f8c66e4c42b3125ae872b7c93b556307"}, + {file = "types_pyyaml-6.0.12.20260724-py3-none-any.whl", hash = "sha256:d57db930a4b2efbc57cf430ec8882765d246929432fa253092f383902329a453"}, + {file = "types_pyyaml-6.0.12.20260724.tar.gz", hash = "sha256:3c1ce1bb73cd5ec02e90390c2b1f00e810d241d8825fd73ff359696839271b6b"}, ] [[package]] name = "types-reportlab" -version = "4.5.1.20260521" +version = "4.5.1.20260724" description = "Typing stubs for reportlab" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_reportlab-4.5.1.20260521-py3-none-any.whl", hash = "sha256:b438c76655dbf24e4b4de157611ff137e1fd670e942d039f8a9321b3fe65cba1"}, - {file = "types_reportlab-4.5.1.20260521.tar.gz", hash = "sha256:072d6d700d42f37bd515a1f92a4298066909d5ada3d40a9f7fd61f414f2691af"}, + {file = "types_reportlab-4.5.1.20260724-py3-none-any.whl", hash = "sha256:182b52f41e346587c97e0d8cd677c5c64a821342497cb1ab4478e2bb19d7d8e4"}, + {file = "types_reportlab-4.5.1.20260724.tar.gz", hash = "sha256:71d3c85fa2055e34803c3a21410db39d4f039b3a6e0db39f9c3a43b202d5997c"}, ] [[package]] name = "types-requests" -version = "2.33.0.20260503" +version = "2.33.0.20260712" description = "Typing stubs for requests" optional = false python-versions = ">=3.10" groups = ["dev"] files = [ - {file = "types_requests-2.33.0.20260503-py3-none-any.whl", hash = "sha256:02aaa7e3577a13471715bb1bddb693cc985ea514f754b503bf033e6a09a3e528"}, - {file = "types_requests-2.33.0.20260503.tar.gz", hash = "sha256:9721b2d9dbee7131f2fb39f20f0ebb1999c18cef4b512c9a7932f3722de7c5f4"}, + {file = "types_requests-2.33.0.20260712-py3-none-any.whl", hash = "sha256:de027e28c171d3da529689cbfa023b0b4eab188c8dfa22fd834eebd2cee6e7bb"}, + {file = "types_requests-2.33.0.20260712.tar.gz", hash = "sha256:2141b67ab534a5c5cd2dac5034f2a35f42e699c5bf185eee608c5246a069d7fb"}, ] [package.dependencies] @@ -6838,14 +6548,14 @@ urllib3 = ">=2" [[package]] name = "typing-extensions" -version = "4.15.0" +version = "4.16.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, - {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, + {file = "typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8"}, + {file = "typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5"}, ] [[package]] @@ -6865,34 +6575,35 @@ typing-extensions = ">=4.12.0" [[package]] name = "tzdata" -version = "2026.2" +version = "2026.3" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" groups = ["main", "dev"] files = [ - {file = "tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7"}, - {file = "tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10"}, + {file = "tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931"}, + {file = "tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415"}, ] markers = {dev = "sys_platform == \"win32\""} [[package]] name = "tzlocal" -version = "5.3.1" +version = "5.4.4" description = "tzinfo object for the local timezone" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d"}, - {file = "tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd"}, + {file = "tzlocal-5.4.4-py3-none-any.whl", hash = "sha256:aae09f0126a8a86fa736be266eb4a471380d26a0de3bc14844e7821fee3e2a15"}, + {file = "tzlocal-5.4.4.tar.gz", hash = "sha256:8dbb8660838688a7b6ba4fed31d18dedf842afb4d47ca050d6d891c2c15f3be4"}, ] [package.dependencies] tzdata = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] -devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] +devenv = ["zest.releaser"] +testing = ["check_manifest", "pyroma", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "ruff"] [[package]] name = "uritemplate" @@ -6929,15 +6640,15 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "uvicorn" -version = "0.46.0" +version = "0.51.0" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.10" groups = ["main"] markers = "sys_platform != \"emscripten\"" files = [ - {file = "uvicorn-0.46.0-py3-none-any.whl", hash = "sha256:bbebbcbed972d162afca128605223022bedd345b7bc7855ce66deb31487a9048"}, - {file = "uvicorn-0.46.0.tar.gz", hash = "sha256:fb9da0926999cc6cb22dc7cd71a94a632f078e6ae47ff683c5c420750fb7413d"}, + {file = "uvicorn-0.51.0-py3-none-any.whl", hash = "sha256:5d38af6cd620f2ae3849fb44fd4879e0890aa1febe8d47eb355fb45d93fe6a5b"}, + {file = "uvicorn-0.51.0.tar.gz", hash = "sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0"}, ] [package.dependencies] @@ -6945,7 +6656,7 @@ click = ">=7.0" h11 = ">=0.8" [package.extras] -standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.20)", "websockets (>=10.4)"] +standard = ["httptools (>=0.8.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.20)", "websockets (>=13.0)"] [[package]] name = "vine" @@ -6961,14 +6672,14 @@ files = [ [[package]] name = "virtualenv" -version = "21.5.1" +version = "21.7.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "virtualenv-21.5.1-py3-none-any.whl", hash = "sha256:55aa670b67bbfb991b03fda39bd3276d92c419d702376e98c5df1c9989a26783"}, - {file = "virtualenv-21.5.1.tar.gz", hash = "sha256:dca3bf98275a59c652b69d68e73433e597d977c2da9198882479d1a7188009c8"}, + {file = "virtualenv-21.7.0-py3-none-any.whl", hash = "sha256:a8370c1c5530fbabf955e40b8fbbc68a431648b10f9433faa587db30a06e51dd"}, + {file = "virtualenv-21.7.0.tar.gz", hash = "sha256:7f9519b9432ff11b6e1a3e94061664efc2ff99ea21780e3cf4f6bd0a5da8b37c"}, ] [package.dependencies] @@ -6991,14 +6702,14 @@ files = [ [[package]] name = "wcwidth" -version = "0.7.0" +version = "0.8.2" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2"}, - {file = "wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0"}, + {file = "wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85"}, + {file = "wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda"}, ] [[package]] @@ -7020,73 +6731,121 @@ test = ["pytest", "websockets"] [[package]] name = "websockets" -version = "16.0" +version = "16.1.1" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false python-versions = ">=3.10" groups = ["main"] files = [ - {file = "websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a"}, - {file = "websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0"}, - {file = "websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957"}, - {file = "websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72"}, - {file = "websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde"}, - {file = "websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3"}, - {file = "websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3"}, - {file = "websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9"}, - {file = "websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35"}, - {file = "websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8"}, - {file = "websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad"}, - {file = "websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d"}, - {file = "websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe"}, - {file = "websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b"}, - {file = "websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5"}, - {file = "websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64"}, - {file = "websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6"}, - {file = "websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac"}, - {file = "websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00"}, - {file = "websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79"}, - {file = "websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39"}, - {file = "websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c"}, - {file = "websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f"}, - {file = "websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1"}, - {file = "websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2"}, - {file = "websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89"}, - {file = "websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea"}, - {file = "websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9"}, - {file = "websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230"}, - {file = "websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c"}, - {file = "websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5"}, - {file = "websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82"}, - {file = "websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8"}, - {file = "websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f"}, - {file = "websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a"}, - {file = "websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156"}, - {file = "websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0"}, - {file = "websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904"}, - {file = "websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4"}, - {file = "websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e"}, - {file = "websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4"}, - {file = "websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1"}, - {file = "websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3"}, - {file = "websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8"}, - {file = "websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d"}, - {file = "websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244"}, - {file = "websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e"}, - {file = "websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641"}, - {file = "websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8"}, - {file = "websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e"}, - {file = "websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944"}, - {file = "websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206"}, - {file = "websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6"}, - {file = "websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd"}, - {file = "websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d"}, - {file = "websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03"}, - {file = "websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da"}, - {file = "websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c"}, - {file = "websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767"}, - {file = "websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec"}, - {file = "websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5"}, + {file = "websockets-16.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:49ae99bdfcae803a885c926bf14f886196e84925395bb3f568fef5c0f0979d7d"}, + {file = "websockets-16.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5bfd1ac19b1b9986a9c95a82d5e23a391ebb09e12c34d7be6094b86efcc35731"}, + {file = "websockets-16.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9246a0d063cfcbcc85f2359dd6876d681213f4790832272aa16641b4ed5d64d4"}, + {file = "websockets-16.1.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1214e673c404684b9bf7154f5cf43b45025b1a6160fac3a9e438e9c1a97e22cb"}, + {file = "websockets-16.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90001d893bc368e302ef168d82130b4e4fdd27b85fa094682df9b667c2d48838"}, + {file = "websockets-16.1.1-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:130937b167a52af203c8d58e78d67705874e82759862e3b9671a452fec4abc87"}, + {file = "websockets-16.1.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9c9f23004a3d40e89c01a7955d186a6cc83418d93b749701944ce2de3e95a1f3"}, + {file = "websockets-16.1.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f55f0b01956a094c8587146d9558c91937e78789c333860ffaf35931a6e5dbc4"}, + {file = "websockets-16.1.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6aaface73b9c71974c6497366d8b9628357f6c9749e09c4ea3610176c63f2ae3"}, + {file = "websockets-16.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dc0fad4933f427acd5b1cec210f3ea6dce7089e1724e4b9ec6ef47c6c04d1b3b"}, + {file = "websockets-16.1.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:f2769a0344a09e9ccf5b3cce538bc75a51b53eff3275d3896310c8552049195d"}, + {file = "websockets-16.1.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f70541f3104339f59f830522d94ebadb1bf47426287381623443d8bb1cdbf33d"}, + {file = "websockets-16.1.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:dc385593a42e31cd6fb60c19f0ecb015b386603818fc2c6c274fb42bd2bb4165"}, + {file = "websockets-16.1.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:387e8e4aa5df2f90b198fa3cad3478822a89cf905b6a6d6c97dc3664689640cc"}, + {file = "websockets-16.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fd46fff7eb62c24804d234f0051c7a8ea81285ad63e0337d3dcf33ca82aee58a"}, + {file = "websockets-16.1.1-cp310-cp310-win32.whl", hash = "sha256:7883388947767080f094950b342b30d35a2a06b849cd967c422fa0db72b40ea9"}, + {file = "websockets-16.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:d57685547e0060cc6fd90ee6a28405d6bd395e525545f13c8d7cd99c78afd79f"}, + {file = "websockets-16.1.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d0fcf657e9f13ff4b177960ab2200237b12994232dfb6df16f1cfe1d4339f93c"}, + {file = "websockets-16.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b852788aa51764e2d8e4cf5493d559326bcae5e38d16ba25ffa322b034df272a"}, + {file = "websockets-16.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1427fb4cf0d72f66333e2cacc3ff5f575bf2d7008166ce991a4a470b21d51a22"}, + {file = "websockets-16.1.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:da4ca1a9d72f9030b3146b8d7022719a9f3d478f61efe6f7dd51d243f61c51b2"}, + {file = "websockets-16.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86d7f0f8bdb25d2c632b72527325e4776430fd5bc61b9118de4e2b8ddb5f5b01"}, + {file = "websockets-16.1.1-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7dfcad78ea1492ee3a9ec765cb7f51bbc17d477107aaf6b22abf7b2558d1c5a0"}, + {file = "websockets-16.1.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fb9a0a6dc3d1b3986cb88091b6899f0396651e0f74e2c9766ab8d6ffc3842e29"}, + {file = "websockets-16.1.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29dfa8114c4a620c69591c5973860f768eac29d3fd6904f37f34266cb219c512"}, + {file = "websockets-16.1.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6ff9417c0ada4d0f7d212f928303e5579bdf3ace4c802fa4afabb30995da58c3"}, + {file = "websockets-16.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fe0b50da2d84535fb4f7b4bfa951280f97ce3d558a0443b541166d609e67b57"}, + {file = "websockets-16.1.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:34420aaa64440ebd51ac72ca8a45ef4626429438c9b02e633ae412ed43f925d3"}, + {file = "websockets-16.1.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a6a61aff018180c9c50b7b0da33bfd29d378af3497429c95006c589a23a11648"}, + {file = "websockets-16.1.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:04fd29a0e2fe9414a95b00e92c67ae51bf900c50c0f8a4b2dafdad621f49ea1d"}, + {file = "websockets-16.1.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5c31aa7e39ee3e8a358573257f1c0bb5c52430d1b637030dd9c8cc2c282926be"}, + {file = "websockets-16.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d14bfb217eb4701e850f1525c9d29d79c44794cdf1c299ead25f39f8c78dea81"}, + {file = "websockets-16.1.1-cp311-cp311-win32.whl", hash = "sha256:2e28e602bb13da44fbe518c1781a88e3b9d4c3d48d02c9bad83e546164336f57"}, + {file = "websockets-16.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:7421fad442de870a8cbf2287d1cad7e706ece0dbfeba5e911df132cbdc1cb56a"}, + {file = "websockets-16.1.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:cc97814dfb786a83b6e2dc2e79351e1b83e6d715647d6887fcabd83026417a00"}, + {file = "websockets-16.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e047dc87ef7ca50f4d309bf775ad4a71711c58556d75d7bd0604b2317f43e94b"}, + {file = "websockets-16.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:01fbdcbac298efe19360b94bc0039c8f746f0220ba570f327577bfee81059175"}, + {file = "websockets-16.1.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f62863e8a00a6d33c3d6566ec0b89f23787b747ffe0c3bc71ec0e76b82c94b1"}, + {file = "websockets-16.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8087e82f842609734c9b5a1330464f8e94e346ba0e18c832c08bafa4b0d63c15"}, + {file = "websockets-16.1.1-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2bb5d041a8307d2e18782e7ce777f6fdb1e8c2f5d09291484b18c294b789d9aa"}, + {file = "websockets-16.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1db4de4a0e95673f7545d393c49eeb0c2f18ac1ef93073218c79d5cdb2ee75ab"}, + {file = "websockets-16.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f17dbe07eb3ea7f99e4df9b7e0efefe80fbf30d37a8cc4d561a0aed310bc8847"}, + {file = "websockets-16.1.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4b57693728576d84ede0a77987ab16881b783d2cd9f1dc180a8fbbc3f79c4428"}, + {file = "websockets-16.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2a636ff1e7a5c4edf71ef0e79adae7f25dba93b4fcbe3dc958733477ffeb0eaf"}, + {file = "websockets-16.1.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d6bec75c290fe484a8ba4cacdf838501e17c06ecfbbf31eede81a9e431bd7751"}, + {file = "websockets-16.1.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:54509b8e92fee4453e152b7558ddef37ce9705a044922f2095a6105e3f80c96f"}, + {file = "websockets-16.1.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:f0aa4aad3b1b69ad3fd85a0fd0952ec64331c762bd77ec51cc814170873890b2"}, + {file = "websockets-16.1.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:42290eb6db4ccaca7012656738214f8514082fb6fa40cdeb61bb9a471b52e383"}, + {file = "websockets-16.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:53260c8930da5771cec89439bff99c20c8cb03ddb9588b980697355a83cd4bd3"}, + {file = "websockets-16.1.1-cp312-cp312-win32.whl", hash = "sha256:1d27fa8462ad6a1cb36206a3d0640b2333340def181fae11ed7f9adeaa5c0747"}, + {file = "websockets-16.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:b436f6ec4fc3a6b4237c84d3f83170ed2b40bb584222f0ac47a0c8a5921980c7"}, + {file = "websockets-16.1.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ab59169ace05dcb49a1d4118f0bde139557adf45091bd85747e36bf5de984dd1"}, + {file = "websockets-16.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5e3b7d601f6f84156b08cc4a5e541c2b50ad7b36cfc302b657a12477c904a5df"}, + {file = "websockets-16.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cd2ca96a082a36964aca83e992f72abeb61b7306c1a6cba4c7d06a7b93750cac"}, + {file = "websockets-16.1.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f5d497865f05bb222cab7016c6034542e84e5f29f49c6fd3f4939cda7197b5b8"}, + {file = "websockets-16.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bae954c382e013d5ea5b190d2830526bfa45ad121c326da0049b8c769f185db6"}, + {file = "websockets-16.1.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e09f753a169951eb4f28c2c774f71069304f66e7277e0f5a2892423599cfa854"}, + {file = "websockets-16.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:024193f8551a2b0eafbdd160911012c4e6c228c28430c84433253299a9e42d6a"}, + {file = "websockets-16.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:aabe464bfd13bd25f4821faf111da6fefdc389f870265a53105580e45b0a2e49"}, + {file = "websockets-16.1.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a28fcbc9b6baf54a2e23f8655f308e4ccc6afdd7266f8fe7954f320dcda0f785"}, + {file = "websockets-16.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79eace538c6a97e96d0d03d4f9d314f9677f5ed85a8a984992ffd90b13cb8a56"}, + {file = "websockets-16.1.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:496af849a472b531f758dbd4d61338f5000538cb1a7b3d20d9d32a264517f509"}, + {file = "websockets-16.1.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5283810d2646741a0d8da2aa733d6aefa0545809afccb2a5d105a26bc45125f1"}, + {file = "websockets-16.1.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4e3b680b1e0a27457e727a0d572fd81dffa87b6dbf8b228ab57da64f7d85aead"}, + {file = "websockets-16.1.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:69159730a823dde3ea8d08783e8d47ef135a6d7e8d44eb127e32b321c9db8e3e"}, + {file = "websockets-16.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ed5bb271084b46530ee2ddc0410537a9961152c5ccba2fc98c5276d992ccba87"}, + {file = "websockets-16.1.1-cp313-cp313-win32.whl", hash = "sha256:cfb70b4eb56cac4da0a83588f3ad50d46beb0690391082f3d4e2d488c70b68ea"}, + {file = "websockets-16.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:d9531d9cbeac99af6f038fb1bc351403531f7d634a2c2e10e2f7c854c6ed5b68"}, + {file = "websockets-16.1.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:443aefe96b7fdb132e2a70806cca1f2af49bb3f28e47abcd7c2e9dcf4d8fa1b8"}, + {file = "websockets-16.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6456ff333092d509127d75a638cb411afae8ff17f092635015d1902efec8a293"}, + {file = "websockets-16.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fce6c48559c86d1ac3632ccb1bebc7d5442fbe79bd9bb0e40379ee54be2a4051"}, + {file = "websockets-16.1.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:92b820d345f7a3fc7b8163949ee92df910f290c3fc517b3d5301c78065adafe1"}, + {file = "websockets-16.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a606d9c24035242a3e256e9d5b77ed9cd6bccfcb7cf993e5ca3c0f6f68fb6a7"}, + {file = "websockets-16.1.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:414e596c75f74e0994084694189d7dc9229fb278e33064d6784b73ffbba3ca31"}, + {file = "websockets-16.1.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:536676848fc5961aca9d20389951f59169508f765637a172403dc5434d722fa0"}, + {file = "websockets-16.1.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:97fd3a0e8b53efa41970ac1dff3d8cf0d2884cadeb4caaf95db7ad1526926ee3"}, + {file = "websockets-16.1.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7b1b19636af86a3c7995d4d028dbe376f39b4bf31541146f9c123582a6c94562"}, + {file = "websockets-16.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:41c8e77f17294c0ac18008a7309b99b34ee72247ef10b6dff4c3f8b5ac29896b"}, + {file = "websockets-16.1.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:9f63bcef7f4b02b06b35fc01c93b96c43b5e88e1e8868676caacf493d5a31f3a"}, + {file = "websockets-16.1.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dab9eb87869da2d6ed3af3f3adf28414baae6ec9d4df355ffc18889132f3436c"}, + {file = "websockets-16.1.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:43e3a9fdd7cbf7ba6040c31fae0faf84ca1474fef777c4e37912f1540f854499"}, + {file = "websockets-16.1.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:056ae37939ed7e9974f364f5864e76e49182622d8f9751ac1903c0d09b013985"}, + {file = "websockets-16.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a0eadbbf2c30f01efa58e1f110eb6fa293261f6b0b1aa38f7f48707107690af9"}, + {file = "websockets-16.1.1-cp314-cp314-win32.whl", hash = "sha256:195c978b065fa40910582464f99d6b15c8b314c68e0546549a55ed83f4735328"}, + {file = "websockets-16.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:4e8d01cc3bcae7bbf8167f944aeafefed590fae5693552bba9794a9df68371cc"}, + {file = "websockets-16.1.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0ffd3031ea8bda8d61762e84220186105ba3b748b3c8da2ae4f7816fac03e573"}, + {file = "websockets-16.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:84a2cef8deffbd9ab8ee0ea546a2a6a7030c28f44e6cdd4547dbfeb489eb8999"}, + {file = "websockets-16.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3df13f73af9b3b38ab1195eb299ecb67a4330c911c97ae04043ff74085728abe"}, + {file = "websockets-16.1.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:23253dd5bcae3f9aaee0a1d30967a8dbd52e5d3cff93a2e5b84df57b77d4750d"}, + {file = "websockets-16.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c1c5705e314449e3308872fe084b8571ce078ee4fc55a98a769bdefe5917392"}, + {file = "websockets-16.1.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:69e52d175a0a7d1e13b4b67ad41c560b7d98e8c6f6126eb0bda496c784faf8c7"}, + {file = "websockets-16.1.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1f79c89b5eb034d1722938a891916582f8f7f503f58ca22518a63c3f2cd18499"}, + {file = "websockets-16.1.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:39f2a024af5c345ffe8fcf1ee18c049c024c94df393bb09b044a6917c77bde43"}, + {file = "websockets-16.1.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:952303a7318d4cbe1011400839bb2051c9f84fa0a35923267f5daba34b15d458"}, + {file = "websockets-16.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:249116b4a76063d930a46391ad56e135c286e4562a18309029fc2c73f4ed4c62"}, + {file = "websockets-16.1.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:61922544a0587a13fd3f53e4c0e5e606510c7b0d9d22c8444e5fae22a06b38cb"}, + {file = "websockets-16.1.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:46dcaa042cd1de6c59e7d9269fa63ff7572b6df40510600b678f0826b3c7af51"}, + {file = "websockets-16.1.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:38565aca3e01ea8734e578fb2118dade0ecb0250533f29e22b8d1a7a196cf4d0"}, + {file = "websockets-16.1.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:42f599f4d48c7e1a3338fdaac3acd075be3b3cf02d4b274f3bf2767aedd3d217"}, + {file = "websockets-16.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dcc04fedf83effaeb9cce98abc9469bb1b42ef85f03e01c8c1f4438ef7555737"}, + {file = "websockets-16.1.1-cp314-cp314t-win32.whl", hash = "sha256:8483c2096363120eea8b07c06ae7304d520f686665fffd4811fad423930a65d7"}, + {file = "websockets-16.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:bcce07e23e5769375158f5efdcdafa8d5cd014b93c6683865b840ed65b96f231"}, + {file = "websockets-16.1.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:820fb8450edddae3812fd58cbc08e2bf22812cb248ecb5f06dbb82119a56e869"}, + {file = "websockets-16.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:125f22dbefaf1554fea66fc83851490edb284ce4f501d37ffed2752f418332d9"}, + {file = "websockets-16.1.1-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:30bbe120437b5648a77d3519b7024ea09530e0b5b18d3698c5a0ae536fe0cc2e"}, + {file = "websockets-16.1.1-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b6b9dadbef0cccd9f4c4ee96b08898afa73e26803bbe0f6aeb5bb12b0074206d"}, + {file = "websockets-16.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56cd5fc4f10a9ea8aa0804bddb7b42506cf9e136046f3b4c27de8fec9e2ecba5"}, + {file = "websockets-16.1.1-py3-none-any.whl", hash = "sha256:6abbd3e82c731c8e531714466acd5d87b5e88ac3243465337ba71d68e23ae7e3"}, + {file = "websockets-16.1.1.tar.gz", hash = "sha256:db234eda965dcce15df96bb9709f587cd87d4d52aaf0e80e2f34ec04c7670c57"}, ] [[package]] @@ -7106,13 +6865,13 @@ h11 = ">=0.16.0,<1" [[package]] name = "xero-python" -version = "14.0.0" +version = "15.0.0" description = "Official Python sdk for Xero API generated by OpenAPI spec for oAuth2" optional = false python-versions = ">=3.5" groups = ["main"] files = [ - {file = "xero_python-14.0.0.tar.gz", hash = "sha256:c5740ccc176b6af67e6f527818b54519c661d089e1128abf751ff440cd5acab7"}, + {file = "xero_python-15.0.0.tar.gz", hash = "sha256:7aa866e166cbb29caf477f86e4936db5895dce85e470fb18aad54759e5fab147"}, ] [package.dependencies] @@ -7123,141 +6882,117 @@ urllib3 = "*" [[package]] name = "yarl" -version = "1.23.0" +version = "1.24.5" description = "Yet another URL library" optional = false python-versions = ">=3.10" groups = ["main"] markers = "python_version < \"3.14\"" files = [ - {file = "yarl-1.23.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cff6d44cb13d39db2663a22b22305d10855efa0fa8015ddeacc40bc59b9d8107"}, - {file = "yarl-1.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c53f8347cd4200f0d70a48ad059cabaf24f5adc6ba08622a23423bc7efa10d"}, - {file = "yarl-1.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a6940a074fb3c48356ed0158a3ca5699c955ee4185b4d7d619be3c327143e05"}, - {file = "yarl-1.23.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed5f69ce7be7902e5c70ea19eb72d20abf7d725ab5d49777d696e32d4fc1811d"}, - {file = "yarl-1.23.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:389871e65468400d6283c0308e791a640b5ab5c83bcee02a2f51295f95e09748"}, - {file = "yarl-1.23.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dda608c88cf709b1d406bdfcd84d8d63cff7c9e577a403c6108ce8ce9dcc8764"}, - {file = "yarl-1.23.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c4fe09e0780c6c3bf2b7d4af02ee2394439d11a523bbcf095cf4747c2932007"}, - {file = "yarl-1.23.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:31c9921eb8bd12633b41ad27686bbb0b1a2a9b8452bfdf221e34f311e9942ed4"}, - {file = "yarl-1.23.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5f10fd85e4b75967468af655228fbfd212bdf66db1c0d135065ce288982eda26"}, - {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:dbf507e9ef5688bada447a24d68b4b58dd389ba93b7afc065a2ba892bea54769"}, - {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:85e9beda1f591bc73e77ea1c51965c68e98dafd0fec72cdd745f77d727466716"}, - {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0e1fdaa14ef51366d7757b45bde294e95f6c8c049194e793eedb8387c86d5993"}, - {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:75e3026ab649bf48f9a10c0134512638725b521340293f202a69b567518d94e0"}, - {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:80e6d33a3d42a7549b409f199857b4fb54e2103fc44fb87605b6663b7a7ff750"}, - {file = "yarl-1.23.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5ec2f42d41ccbd5df0270d7df31618a8ee267bfa50997f5d720ddba86c4a83a6"}, - {file = "yarl-1.23.0-cp310-cp310-win32.whl", hash = "sha256:debe9c4f41c32990771be5c22b56f810659f9ddf3d63f67abfdcaa2c6c9c5c1d"}, - {file = "yarl-1.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f043cb8a2d71c981c09c510da013bc79fd661f5c60139f00dd3c3cc4f2ffb"}, - {file = "yarl-1.23.0-cp310-cp310-win_arm64.whl", hash = "sha256:263cd4f47159c09b8b685890af949195b51d1aa82ba451c5847ca9bc6413c220"}, - {file = "yarl-1.23.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b35d13d549077713e4414f927cdc388d62e543987c572baee613bf82f11a4b99"}, - {file = "yarl-1.23.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbb0fef01f0c6b38cb0f39b1f78fc90b807e0e3c86a7ff3ce74ad77ce5c7880c"}, - {file = "yarl-1.23.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dc52310451fc7c629e13c4e061cbe2dd01684d91f2f8ee2821b083c58bd72432"}, - {file = "yarl-1.23.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2c6b50c7b0464165472b56b42d4c76a7b864597007d9c085e8b63e185cf4a7a"}, - {file = "yarl-1.23.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:aafe5dcfda86c8af00386d7781d4c2181b5011b7be3f2add5e99899ea925df05"}, - {file = "yarl-1.23.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9ee33b875f0b390564c1fb7bc528abf18c8ee6073b201c6ae8524aca778e2d83"}, - {file = "yarl-1.23.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4c41e021bc6d7affb3364dc1e1e5fa9582b470f283748784bd6ea0558f87f42c"}, - {file = "yarl-1.23.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99c8a9ed30f4164bc4c14b37a90208836cbf50d4ce2a57c71d0f52c7fb4f7598"}, - {file = "yarl-1.23.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2af5c81a1f124609d5f33507082fc3f739959d4719b56877ab1ee7e7b3d602b"}, - {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6b41389c19b07c760c7e427a3462e8ab83c4bb087d127f0e854c706ce1b9215c"}, - {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1dc702e42d0684f42d6519c8d581e49c96cefaaab16691f03566d30658ee8788"}, - {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0e40111274f340d32ebcc0a5668d54d2b552a6cca84c9475859d364b380e3222"}, - {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:4764a6a7588561a9aef92f65bda2c4fb58fe7c675c0883862e6df97559de0bfb"}, - {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:03214408cfa590df47728b84c679ae4ef00be2428e11630277be0727eba2d7cc"}, - {file = "yarl-1.23.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:170e26584b060879e29fac213e4228ef063f39128723807a312e5c7fec28eff2"}, - {file = "yarl-1.23.0-cp311-cp311-win32.whl", hash = "sha256:51430653db848d258336cfa0244427b17d12db63d42603a55f0d4546f50f25b5"}, - {file = "yarl-1.23.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf49a3ae946a87083ef3a34c8f677ae4243f5b824bfc4c69672e72b3d6719d46"}, - {file = "yarl-1.23.0-cp311-cp311-win_arm64.whl", hash = "sha256:b39cb32a6582750b6cc77bfb3c49c0f8760dc18dc96ec9fb55fbb0f04e08b928"}, - {file = "yarl-1.23.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1932b6b8bba8d0160a9d1078aae5838a66039e8832d41d2992daa9a3a08f7860"}, - {file = "yarl-1.23.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:411225bae281f114067578891bc75534cfb3d92a3b4dfef7a6ca78ba354e6069"}, - {file = "yarl-1.23.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13a563739ae600a631c36ce096615fe307f131344588b0bc0daec108cdb47b25"}, - {file = "yarl-1.23.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cbf44c5cb4a7633d078788e1b56387e3d3cf2b8139a3be38040b22d6c3221c8"}, - {file = "yarl-1.23.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53ad387048f6f09a8969631e4de3f1bf70c50e93545d64af4f751b2498755072"}, - {file = "yarl-1.23.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4a59ba56f340334766f3a4442e0efd0af895fae9e2b204741ef885c446b3a1a8"}, - {file = "yarl-1.23.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:803a3c3ce4acc62eaf01eaca1208dcf0783025ef27572c3336502b9c232005e7"}, - {file = "yarl-1.23.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3d2bff8f37f8d0f96c7ec554d16945050d54462d6e95414babaa18bfafc7f51"}, - {file = "yarl-1.23.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c75eb09e8d55bceb4367e83496ff8ef2bc7ea6960efb38e978e8073ea59ecb67"}, - {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877b0738624280e34c55680d6054a307aa94f7d52fa0e3034a9cc6e790871da7"}, - {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b5405bb8f0e783a988172993cfc627e4d9d00432d6bbac65a923041edacf997d"}, - {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:1c3a3598a832590c5a3ce56ab5576361b5688c12cb1d39429cf5dba30b510760"}, - {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8419ebd326430d1cbb7efb5292330a2cf39114e82df5cc3d83c9a0d5ebeaf2f2"}, - {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:be61f6fff406ca40e3b1d84716fde398fc08bc63dd96d15f3a14230a0973ed86"}, - {file = "yarl-1.23.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ceb13c5c858d01321b5d9bb65e4cf37a92169ea470b70fec6f236b2c9dd7e34"}, - {file = "yarl-1.23.0-cp312-cp312-win32.whl", hash = "sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d"}, - {file = "yarl-1.23.0-cp312-cp312-win_amd64.whl", hash = "sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e"}, - {file = "yarl-1.23.0-cp312-cp312-win_arm64.whl", hash = "sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9"}, - {file = "yarl-1.23.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:16c6994ac35c3e74fb0ae93323bf8b9c2a9088d55946109489667c510a7d010e"}, - {file = "yarl-1.23.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a42e651629dafb64fd5b0286a3580613702b5809ad3f24934ea87595804f2c5"}, - {file = "yarl-1.23.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7c6b9461a2a8b47c65eef63bb1c76a4f1c119618ffa99ea79bc5bb1e46c5821b"}, - {file = "yarl-1.23.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2569b67d616eab450d262ca7cb9f9e19d2f718c70a8b88712859359d0ab17035"}, - {file = "yarl-1.23.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e9d9a4d06d3481eab79803beb4d9bd6f6a8e781ec078ac70d7ef2dcc29d1bea5"}, - {file = "yarl-1.23.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f514f6474e04179d3d33175ed3f3e31434d3130d42ec153540d5b157deefd735"}, - {file = "yarl-1.23.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fda207c815b253e34f7e1909840fd14299567b1c0eb4908f8c2ce01a41265401"}, - {file = "yarl-1.23.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34b6cf500e61c90f305094911f9acc9c86da1a05a7a3f5be9f68817043f486e4"}, - {file = "yarl-1.23.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d7504f2b476d21653e4d143f44a175f7f751cd41233525312696c76aa3dbb23f"}, - {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:578110dd426f0d209d1509244e6d4a3f1a3e9077655d98c5f22583d63252a08a"}, - {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:609d3614d78d74ebe35f54953c5bbd2ac647a7ddb9c30a5d877580f5e86b22f2"}, - {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4966242ec68afc74c122f8459abd597afd7d8a60dc93d695c1334c5fd25f762f"}, - {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e0fd068364a6759bc794459f0a735ab151d11304346332489c7972bacbe9e72b"}, - {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:39004f0ad156da43e86aa71f44e033de68a44e5a31fc53507b36dd253970054a"}, - {file = "yarl-1.23.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e5723c01a56c5028c807c701aa66722916d2747ad737a046853f6c46f4875543"}, - {file = "yarl-1.23.0-cp313-cp313-win32.whl", hash = "sha256:1b6b572edd95b4fa8df75de10b04bc81acc87c1c7d16bcdd2035b09d30acc957"}, - {file = "yarl-1.23.0-cp313-cp313-win_amd64.whl", hash = "sha256:baaf55442359053c7d62f6f8413a62adba3205119bcb6f49594894d8be47e5e3"}, - {file = "yarl-1.23.0-cp313-cp313-win_arm64.whl", hash = "sha256:fb4948814a2a98e3912505f09c9e7493b1506226afb1f881825368d6fb776ee3"}, - {file = "yarl-1.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:aecfed0b41aa72b7881712c65cf764e39ce2ec352324f5e0837c7048d9e6daaa"}, - {file = "yarl-1.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a41bcf68efd19073376eb8cf948b8d9be0af26256403e512bb18f3966f1f9120"}, - {file = "yarl-1.23.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cde9a2ecd91668bcb7f077c4966d8ceddb60af01b52e6e3e2680e4cf00ad1a59"}, - {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5023346c4ee7992febc0068e7593de5fa2bf611848c08404b35ebbb76b1b0512"}, - {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1009abedb49ae95b136a8904a3f71b342f849ffeced2d3747bf29caeda218c4"}, - {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a8d00f29b42f534cc8aa3931cfe773b13b23e561e10d2b26f27a8d309b0e82a1"}, - {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:95451e6ce06c3e104556d73b559f5da6c34a069b6b62946d3ad66afcd51642ea"}, - {file = "yarl-1.23.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:531ef597132086b6cf96faa7c6c1dcd0361dd5f1694e5cc30375907b9b7d3ea9"}, - {file = "yarl-1.23.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:88f9fb0116fbfcefcab70f85cf4b74a2b6ce5d199c41345296f49d974ddb4123"}, - {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e7b0460976dc75cb87ad9cc1f9899a4b97751e7d4e77ab840fc9b6d377b8fd24"}, - {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:115136c4a426f9da976187d238e84139ff6b51a20839aa6e3720cd1026d768de"}, - {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ead11956716a940c1abc816b7df3fa2b84d06eaed8832ca32f5c5e058c65506b"}, - {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:fe8f8f5e70e6dbdfca9882cd9deaac058729bcf323cf7a58660901e55c9c94f6"}, - {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a0e317df055958a0c1e79e5d2aa5a5eaa4a6d05a20d4b0c9c3f48918139c9fc6"}, - {file = "yarl-1.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f0fd84de0c957b2d280143522c4f91a73aada1923caee763e24a2b3fda9f8a5"}, - {file = "yarl-1.23.0-cp313-cp313t-win32.whl", hash = "sha256:93a784271881035ab4406a172edb0faecb6e7d00f4b53dc2f55919d6c9688595"}, - {file = "yarl-1.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dd00607bffbf30250fe108065f07453ec124dbf223420f57f5e749b04295e090"}, - {file = "yarl-1.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ac09d42f48f80c9ee1635b2fcaa819496a44502737660d3c0f2ade7526d29144"}, - {file = "yarl-1.23.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:21d1b7305a71a15b4794b5ff22e8eef96ff4a6d7f9657155e5aa419444b28912"}, - {file = "yarl-1.23.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:85610b4f27f69984932a7abbe52703688de3724d9f72bceb1cca667deff27474"}, - {file = "yarl-1.23.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23f371bd662cf44a7630d4d113101eafc0cfa7518a2760d20760b26021454719"}, - {file = "yarl-1.23.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a80f77dc1acaaa61f0934176fccca7096d9b1ff08c8ba9cddf5ae034a24319"}, - {file = "yarl-1.23.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bd654fad46d8d9e823afbb4f87c79160b5a374ed1ff5bde24e542e6ba8f41434"}, - {file = "yarl-1.23.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:682bae25f0a0dd23a056739f23a134db9f52a63e2afd6bfb37ddc76292bbd723"}, - {file = "yarl-1.23.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a82836cab5f197a0514235aaf7ffccdc886ccdaa2324bc0aafdd4ae898103039"}, - {file = "yarl-1.23.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c57676bdedc94cd3bc37724cf6f8cd2779f02f6aba48de45feca073e714fe52"}, - {file = "yarl-1.23.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7f8dc16c498ff06497c015642333219871effba93e4a2e8604a06264aca5c5c"}, - {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5ee586fb17ff8f90c91cf73c6108a434b02d69925f44f5f8e0d7f2f260607eae"}, - {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:17235362f580149742739cc3828b80e24029d08cbb9c4bda0242c7b5bc610a8e"}, - {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:0793e2bd0cf14234983bbb371591e6bea9e876ddf6896cdcc93450996b0b5c85"}, - {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3650dc2480f94f7116c364096bc84b1d602f44224ef7d5c7208425915c0475dd"}, - {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f40e782d49630ad384db66d4d8b73ff4f1b8955dc12e26b09a3e3af064b3b9d6"}, - {file = "yarl-1.23.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94f8575fbdf81749008d980c17796097e645574a3b8c28ee313931068dad14fe"}, - {file = "yarl-1.23.0-cp314-cp314-win32.whl", hash = "sha256:c8aa34a5c864db1087d911a0b902d60d203ea3607d91f615acd3f3108ac32169"}, - {file = "yarl-1.23.0-cp314-cp314-win_amd64.whl", hash = "sha256:63e92247f383c85ab00dd0091e8c3fa331a96e865459f5ee80353c70a4a42d70"}, - {file = "yarl-1.23.0-cp314-cp314-win_arm64.whl", hash = "sha256:70efd20be968c76ece7baa8dafe04c5be06abc57f754d6f36f3741f7aa7a208e"}, - {file = "yarl-1.23.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:9a18d6f9359e45722c064c97464ec883eb0e0366d33eda61cb19a244bf222679"}, - {file = "yarl-1.23.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:2803ed8b21ca47a43da80a6fd1ed3019d30061f7061daa35ac54f63933409412"}, - {file = "yarl-1.23.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:394906945aa8b19fc14a61cf69743a868bb8c465efe85eee687109cc540b98f4"}, - {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:71d006bee8397a4a89f469b8deb22469fe7508132d3c17fa6ed871e79832691c"}, - {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:62694e275c93d54f7ccedcfef57d42761b2aad5234b6be1f3e3026cae4001cd4"}, - {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31de1613658308efdb21ada98cbc86a97c181aa050ba22a808120bb5be3ab94"}, - {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb1e8b8d66c278b21d13b0a7ca22c41dd757a7c209c6b12c313e445c31dd3b28"}, - {file = "yarl-1.23.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50f9d8d531dfb767c565f348f33dd5139a6c43f5cbdf3f67da40d54241df93f6"}, - {file = "yarl-1.23.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:575aa4405a656e61a540f4a80eaa5260f2a38fff7bfdc4b5f611840d76e9e277"}, - {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:041b1a4cefacf65840b4e295c6985f334ba83c30607441ae3cf206a0eed1a2e4"}, - {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:d38c1e8231722c4ce40d7593f28d92b5fc72f3e9774fe73d7e800ec32299f63a"}, - {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d53834e23c015ee83a99377db6e5e37d8484f333edb03bd15b4bc312cc7254fb"}, - {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2e27c8841126e017dd2a054a95771569e6070b9ee1b133366d8b31beb5018a41"}, - {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:76855800ac56f878847a09ce6dba727c93ca2d89c9e9d63002d26b916810b0a2"}, - {file = "yarl-1.23.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e09fd068c2e169a7070d83d3bde728a4d48de0549f975290be3c108c02e499b4"}, - {file = "yarl-1.23.0-cp314-cp314t-win32.whl", hash = "sha256:73309162a6a571d4cbd3b6a1dcc703c7311843ae0d1578df6f09be4e98df38d4"}, - {file = "yarl-1.23.0-cp314-cp314t-win_amd64.whl", hash = "sha256:4503053d296bc6e4cbd1fad61cf3b6e33b939886c4f249ba7c78b602214fabe2"}, - {file = "yarl-1.23.0-cp314-cp314t-win_arm64.whl", hash = "sha256:44bb7bef4ea409384e3f8bc36c063d77ea1b8d4a5b2706956c0d6695f07dcc25"}, - {file = "yarl-1.23.0-py3-none-any.whl", hash = "sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f"}, - {file = "yarl-1.23.0.tar.gz", hash = "sha256:53b1ea6ca88ebd4420379c330aea57e258408dd0df9af0992e5de2078dc9f5d5"}, + {file = "yarl-1.24.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88f50c94e21a0a7f14042c015b0eba1881af78562e7bf007e0033e624da59750"}, + {file = "yarl-1.24.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6efbccc3d7f75d5b03105172a8dc86d82ba4da86817952529dd93185f4a88be2"}, + {file = "yarl-1.24.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0ebfaffe1a16cb72141c8e09f18cc76856dbe58639f393a4f2b26e474b96b871"}, + {file = "yarl-1.24.5-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ac73abdc7ab75610f95a8fd994c6457e87752b02a63987e188f937a1fc180f0"}, + {file = "yarl-1.24.5-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4d97a951a81039050e45f04e96689b58b8243fa5e62aa14fe67cb6075300885e"}, + {file = "yarl-1.24.5-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fe7b7bb170daccbba19ad33012d2b15f1e7942296fd4d45fc1b79013da8cc0f2"}, + {file = "yarl-1.24.5-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:89a1bbb58e0e3f7a283653d854b1e95d65e5cfd4af224dac5f02629ec1a3e621"}, + {file = "yarl-1.24.5-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7fa5e51397466ea7e98de493fa2ff1b8193cfef8a7b0f9b4842f92d342df0dba"}, + {file = "yarl-1.24.5-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4103b77b8a8225e413107d2349b65eb3c1c52627b5cc5c3c4c1c6a798b218950"}, + {file = "yarl-1.24.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f9f3e9c8a9ecffa57bef8fb4fa19e5fa4d2d8307cf6bac5b1fca5e5860f4ba00"}, + {file = "yarl-1.24.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c0ebc836c47a6477e182169c6a476fc691d12b518894bf7dd2572f0d59f1c7ed"}, + {file = "yarl-1.24.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:96d30286dd02679e32a39aa8f0b7498fc847fcda46cfc09df5513e82ce252440"}, + {file = "yarl-1.24.5-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:fd8c81f346b58f45818d09ea11db69a8d5fd34a224b79871f6d44f12cd7977b1"}, + {file = "yarl-1.24.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:5c55256dee8f4b27bfbf636c8363383c7c8db7890c7cba5217d7bd5f5f21dab6"}, + {file = "yarl-1.24.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9f4d8cf085a4c6a40fb97ea0f46938a8df43c85d31f9d45e2a8867ea9293790d"}, + {file = "yarl-1.24.5-cp310-cp310-win_amd64.whl", hash = "sha256:240cbec09667c1fed4c6cd0060b9ec57332427d7441289a2ed8875dc9fb2b224"}, + {file = "yarl-1.24.5-cp310-cp310-win_arm64.whl", hash = "sha256:8a6987eaad834cb32dd57d9d582225f0054a5d1af706ccfbbdba735af4927e13"}, + {file = "yarl-1.24.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2c1fe720934a16ea8e7146175cba2126f87f54912c8c5435e7f7c7a51ef808d3"}, + {file = "yarl-1.24.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c687ed078e145f5fd53a14854beff320e1d2ab76df03e2009c98f39a0f68f39a"}, + {file = "yarl-1.24.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:709f1efed56c4a145793c046cd4939f9959bcd818979a787b77d8e09c57a0840"}, + {file = "yarl-1.24.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:874019bd513008b009f58657134e5d0c5e030b3559bd0553976837adf52fe966"}, + {file = "yarl-1.24.5-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a4582acf7ef76482f6f511ebaf1946dae7f2e85ec4728b81a678c01df63bd723"}, + {file = "yarl-1.24.5-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2cabe6546e41dabe439999a23fcb5246e0c3b595b4315b96ef755252be90caeb"}, + {file = "yarl-1.24.5-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:17f57620f5475b3c69109376cc87e42a7af5db13c9398e4292772a706ff10780"}, + {file = "yarl-1.24.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:570fec8fbd22b032733625f03f10b7ff023bc399213db15e72a7acaef28c2f4e"}, + {file = "yarl-1.24.5-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5fede79c6f73ff2c3ef822864cb1ada23196e62756df53bc6231d351a49516a2"}, + {file = "yarl-1.24.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8ccf9aca873b767977c73df497a85dbedee4ee086ae9ae49dc461333b9b79f58"}, + {file = "yarl-1.24.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ad5d8201d310b031e6cd839d9bac2d4e5a01533ce5d3d5b50b7de1ef3af1de61"}, + {file = "yarl-1.24.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:841f0852f48fefea3b12c9dfec00704dfa3aef5215d0e3ce564bb3d7cd8d57c6"}, + {file = "yarl-1.24.5-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:9baafc71b04f8f4bb0703b21d6fc9f0c30b346c636a532ff16ec8491a5ea4b1f"}, + {file = "yarl-1.24.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:d897129df1a22b12aeed2c2c98df0785a2e8e6e0bde87b389491d0025c187077"}, + {file = "yarl-1.24.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dd625535328fd9882374356269227670189adfcc6a2d90284f323c05862eecbd"}, + {file = "yarl-1.24.5-cp311-cp311-win_amd64.whl", hash = "sha256:f4239bbec5a3577ddb49e4b50aeb32d8e5792098262ae2f63723f916a29b1a25"}, + {file = "yarl-1.24.5-cp311-cp311-win_arm64.whl", hash = "sha256:3ac6aff147deb9c09461b2d4bbdf6256831198f5d8a23f5d37138213090b6d8a"}, + {file = "yarl-1.24.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d693396e5aea78db03decd60aec9ece16c9b40ba00a587f089615ff4e718a81d"}, + {file = "yarl-1.24.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3363fcc96e665878946ad7a106b9a13eac0541766a690ef287c0232ac768b6ec"}, + {file = "yarl-1.24.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9d399bdcfb4a0f659b9b3788bbc89babe63d9a6a65aacdf4d4e7065ff2e6316c"}, + {file = "yarl-1.24.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90333fd89b43c0d08ac85f3f1447593fc2c66de18c3d6378d7125ea118dc7a54"}, + {file = "yarl-1.24.5-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:665b0a2c463cc9423dd647e0bfd9f4ccc9b50f768c55304d5e9f80b177c1de12"}, + {file = "yarl-1.24.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e006d3a974c4ee19512e5f058abedb6eef36a5e553c14812bdeba1758d812e6d"}, + {file = "yarl-1.24.5-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e7d42c531243450ef0d4d9c172e7ed6ef052640f195629065041b5add4e058d1"}, + {file = "yarl-1.24.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f08c7513ecef5aad65687bfdf6bc601ae9fccd04a42904501f8f7141abad9eb9"}, + {file = "yarl-1.24.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6c95b17fe34ed802f17e205112e6e10db92275c34fee290aa9bdc55a9c724027"}, + {file = "yarl-1.24.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:56b149b22de33b23b0c6077ab9518c6dcb538ad462e1830e68d06591ccf6e38b"}, + {file = "yarl-1.24.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a8fe66b8f300da93798025a785a5b90b42f3810dc2b72283ff84a41aaaebc293"}, + {file = "yarl-1.24.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:377fe3732edbaf78ee74efdf2c9f49f6e99f20e7f9d2649fda3eb4badd77d76e"}, + {file = "yarl-1.24.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e8ffa78582120024f476a611d7befc123cee59e47e8309d470cf667d806e613b"}, + {file = "yarl-1.24.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:daba5e594f06114e37db186efd2dd916609071e59daca901a0a2e71f02b142ce"}, + {file = "yarl-1.24.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:65be18ec59496c13908f02a2472751d9ef840b4f3fb5726f129306bf6a2a7bba"}, + {file = "yarl-1.24.5-cp312-cp312-win_amd64.whl", hash = "sha256:a929d878fec099030c292803b31e5d5540a7b6a31e6a3cc76cb4685fc2a2f51b"}, + {file = "yarl-1.24.5-cp312-cp312-win_arm64.whl", hash = "sha256:7ce27823052e2013b597e0c738b13e7e36b8ccb9400df8959417b052ab0fd92c"}, + {file = "yarl-1.24.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:79af890482fc94648e8cde4c68620378f7fef60932710fa17a66abc039244da2"}, + {file = "yarl-1.24.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46c2f213e23a04b93a392942d782eb9e413e6ef6bf7c8c53884e599a5c174dcb"}, + {file = "yarl-1.24.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92ab3e11448f2ff7bf53c5a26eff0edc086898ec8b21fb154b85839ce1d88075"}, + {file = "yarl-1.24.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ebb0ec7f17803063d5aeb982f3b1bd2b2f4e4fae6751226cbd6ba1fcfe9e63ff"}, + {file = "yarl-1.24.5-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:82632daed195dcc8ea664e8556dc9bdbd671960fb3776bd92806ce05792c2448"}, + {file = "yarl-1.24.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:53e549287ef628fecba270045c9701b0c564563a9b0577d24a4ec75b8ab8040f"}, + {file = "yarl-1.24.5-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fcd3b77e2f17bbe4ca56ec7bcb07992647d19d0b9c05d84886dcd6f9eb810afd"}, + {file = "yarl-1.24.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d46b86567dd4e248c6c159fcbcdcce01e0a5c8a7cd2334a0fff759d0fa075b16"}, + {file = "yarl-1.24.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7f72c74aa99359e27a2ee8d6613fefa28b5f76a983c083074dfc2aaa4ab46213"}, + {file = "yarl-1.24.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3f45789ce415a7ec0820dc4f82925f9b5f7732070be1dec1f5f23ec381435a24"}, + {file = "yarl-1.24.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6e73e7fe93f17a7b191f52ec9da9dd8c06a8fe735a1ecbd13b97d1c723bff385"}, + {file = "yarl-1.24.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4a36f9becdd4c5c52a20c3e9484128b070b1dcfc8944c006f3a528295a359a9c"}, + {file = "yarl-1.24.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:7bcbe0fcf850eae67b6b01749815a4f7161c560a844c769ad7b48fcd99f791c4"}, + {file = "yarl-1.24.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:24e861e9630e0daddcb9191fb187f60f034e17a4426f8101279f0c475cd74144"}, + {file = "yarl-1.24.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9335a099ad87287c37fe5d1a982ff392fa5efe5d14b40a730b1ec1d6a41382b4"}, + {file = "yarl-1.24.5-cp313-cp313-win_amd64.whl", hash = "sha256:2dbe06fc16bc91502bca713704022182e5729861ae00277c3a23354b40929740"}, + {file = "yarl-1.24.5-cp313-cp313-win_arm64.whl", hash = "sha256:6b8536851f9f65e7f00c7a1d49ba7f2be0ffe2c11555367fc9f50d9f842410a1"}, + {file = "yarl-1.24.5-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:2729fcfc4f6a596fb0c50f32090400aa9367774ac296a00387e65098c0befa76"}, + {file = "yarl-1.24.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ff330d3c30db4eb6b01d79e29d2d0b407a7ecad39cfd9ec993ece57396a2ec0d"}, + {file = "yarl-1.24.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e42d75862735da90e7fc5a7b23db0c976f737113a54b3c9777a9b665e9cbff75"}, + {file = "yarl-1.24.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3732e66413163e72508da9eff9ce9d2846fde51fae45d3605393d3e6cd303e9"}, + {file = "yarl-1.24.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5b8ee53be440a0cffc991a27be3057e0530122548dbe7c0892df08822fce5ede"}, + {file = "yarl-1.24.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:af3aefa655adb5869491fa907e652290386800ae99cc50095cba71e2c6aefdca"}, + {file = "yarl-1.24.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2120b96872df4a117cde97d270bac96aea7cc52205d305cf4611df694a487027"}, + {file = "yarl-1.24.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:66410eb6345d467151934b49bfa70fb32f5b35a6140baa40ad97d6436abea2e9"}, + {file = "yarl-1.24.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4af7b7e1be0a69bee8210735fe6dcfc38879adfac6d62e789d53ba432d1ffa41"}, + {file = "yarl-1.24.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa139875ff98ab97da323cfadfaff08900d1ad42f1b5087b0b812a55c5a06373"}, + {file = "yarl-1.24.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:0055afc45e864b92729ac7600e2d102c17bef060647e74bca75fa84d66b9ff36"}, + {file = "yarl-1.24.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f0e466ed7511fe9d459a819edbc6c2585c0b6eabde9fa8a8947552468a7a6ef0"}, + {file = "yarl-1.24.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:f141474e85b7e54998ec5180530a7cda99ab29e282fa50e0756d89981a9b43c5"}, + {file = "yarl-1.24.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:e2935f8c39e3b03e83519292d78f075189978f3f4adc15a78144c7c8e2a1cba5"}, + {file = "yarl-1.24.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9d1216a7f6f77836617dba35687c5b78a4170afc3c3f18fc788f785ba26565c4"}, + {file = "yarl-1.24.5-cp314-cp314-win_amd64.whl", hash = "sha256:5ba4f78df2bcc19f764a4b26a8a4f5049c110090ad5825993aacb052bf8003ad"}, + {file = "yarl-1.24.5-cp314-cp314-win_arm64.whl", hash = "sha256:9e4e16c73d717c5cf27626c524d0a2e261ad20e46932b2670f64ad5dde23e26f"}, + {file = "yarl-1.24.5-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e1ae548a9d901adca07899a4147a7c826bbcc06239d3ce9a59f57886a28a4c88"}, + {file = "yarl-1.24.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ff405d91509d88e8d44129cd87b18d70acd1f0c1aeabd7bc3c46792b1fe2acba"}, + {file = "yarl-1.24.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:47e98aab9d8d82ff682e7b0b5dded33bf138a32b817fcf7fa3b27b2d7c412928"}, + {file = "yarl-1.24.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f0a658a6d3fafee5c6f63c58f3e785c8c43c93fbc02bf9f2b6663f8185e0971f"}, + {file = "yarl-1.24.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4377407001ca3c057773f44d8ddd6358fa5f691407c1ba92210bd3cf8d9e4c95"}, + {file = "yarl-1.24.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7c0494a31a1ac5461a226e7947a9c9b78c44e1dc7185164fa7e9651557a5d9bc"}, + {file = "yarl-1.24.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a7cff474ab7cd149765bb784cf6d78b32e18e20473fb7bda860bce98ab58e9da"}, + {file = "yarl-1.24.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cbb833ccacdb5519eff9b8b71ee618cc2801c878e77e288775d77c3a2ced858a"}, + {file = "yarl-1.24.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:82f75e05912e84b7a0fe57075d9c59de3cb352b928330f2eb69b2e1f54c3e1f0"}, + {file = "yarl-1.24.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:16a2f5010280020e90f5330257e6944bc33e73593b136cc5a241e6c1dc292498"}, + {file = "yarl-1.24.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:ffcd54362564dc1a30fb74d8b8a6e5a6b11ebd5e27266adc3b7427a21a6c9104"}, + {file = "yarl-1.24.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0465ec8cedc2349b97a6b595ace64084a50c6e839eca40aa0626f38b8350e331"}, + {file = "yarl-1.24.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4db9aecb141cb7a5447171b57aa1ed3a8fee06af40b992ffc31206c0b0121550"}, + {file = "yarl-1.24.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:f540c013589084679a6c7fac07096b10159737918174f5dfc5e11bf5bca4dfe6"}, + {file = "yarl-1.24.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a61834fb15d81322d872eaafd333838ae7c9cea84067f232656f75965933d047"}, + {file = "yarl-1.24.5-cp314-cp314t-win_amd64.whl", hash = "sha256:5c88e5815a49d289e599f3513aa7fde0bc2092ff188f99c940f007f90f53d104"}, + {file = "yarl-1.24.5-cp314-cp314t-win_arm64.whl", hash = "sha256:cf139c02f5f23ef6532040a30ff662c00a318c952334f211046b8e60b7f17688"}, + {file = "yarl-1.24.5-py3-none-any.whl", hash = "sha256:a33700d13d9b7d84fd10947b09ff69fb9a792e519c8cb9764a3ca70baa6c23a7"}, + {file = "yarl-1.24.5.tar.gz", hash = "sha256:e81b83143bee16329c23db3c1b2d82b29892fcbcb849186d2f6e98a5abe9a57f"}, ] [package.dependencies] @@ -7267,25 +7002,25 @@ propcache = ">=0.2.1" [[package]] name = "zipp" -version = "3.23.1" +version = "4.1.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" groups = ["main"] files = [ - {file = "zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc"}, - {file = "zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110"}, + {file = "zipp-4.1.0-py3-none-any.whl", hash = "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f"}, + {file = "zipp-4.1.0.tar.gz", hash = "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] +check = ["pytest-checkdocs (>=2.14)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] +enabler = ["pytest-enabler (>=3.4)"] test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] -type = ["pytest-mypy"] +type = ["pytest-mypy (>=1.0.1) ; platform_python_implementation != \"PyPy\""] [metadata] lock-version = "2.1" python-versions = "^3.12" -content-hash = "756da8093f691b661edcbaf99d80034204232c29da81ba80ca424bb1036075b9" +content-hash = "32c92b95ab1f1029afef8dd5a7394fedb4bfb140796e9367a543d6aae1f672e3" diff --git a/pyproject.toml b/pyproject.toml index fa033722d..e1e04e0a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ pdf2image = "^1.17.0" gunicorn = "^26.0.0" pdfplumber = "^0.11.6" google-genai = ">=1.19,<3.0" -holidays = ">=0.93,<0.101" +holidays = ">=0.93,<0.102" djangorestframework-simplejwt = "^5.5.1" beautifulsoup4 = "^4.13.4" selenium = "^4.34.2" @@ -40,7 +40,6 @@ lxml = "^6.0.2" django-celery-beat = "^2.6" django-celery-results = "^2.5" google-api-python-client = "^2.171.0" -google-generativeai = "^0.8.5" openpyxl = "^3.1.5" faker = "^40.11.1" mistralai = "^2.1.3" diff --git a/requirements.txt b/requirements.txt index 9deb27a0d..dd656a6dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,44 +1,43 @@ # autogenerated from poetry.lock via poetry export -aiohappyeyeballs==2.6.1 ; python_version >= "3.12" and python_version < "3.14" -aiohttp==3.14.1 ; python_version >= "3.12" and python_version < "3.14" +aiohappyeyeballs==2.7.1 ; python_version >= "3.12" and python_version < "3.14" +aiohttp==3.14.3 ; python_version >= "3.12" and python_version < "3.14" aiosignal==1.4.0 ; python_version >= "3.12" and python_version < "3.14" amqp==5.3.1 ; python_version >= "3.12" and python_version < "4.0" -annotated-doc==0.0.4 ; python_version >= "3.12" and python_version < "3.14" -annotated-types==0.7.0 ; python_version >= "3.12" and python_version < "4.0" +annotated-types==0.8.0 ; python_version >= "3.12" and python_version < "4.0" anthropic==0.112.0 ; python_version >= "3.12" and python_version < "4.0" -anyio==4.13.0 ; python_version >= "3.12" and python_version < "4.0" -asgiref==3.11.1 ; python_version >= "3.12" and python_version < "4.0" -ast-serialize==0.4.0 ; python_version >= "3.12" and python_version < "4.0" +anyio==4.14.2 ; python_version >= "3.12" and python_version < "4.0" +asgiref==3.12.1 ; python_version >= "3.12" and python_version < "4.0" +ast-serialize==0.6.0 ; python_version >= "3.12" and python_version < "4.0" astroid==4.0.4 ; python_version >= "3.12" and python_version < "4.0" attrs==26.1.0 ; python_version >= "3.12" and python_version < "4.0" autoflake==2.3.3 ; python_version >= "3.12" and python_version < "4.0" autopep8==2.3.2 ; python_version >= "3.12" and python_version < "4.0" -beautifulsoup4==4.14.3 ; python_version >= "3.12" and python_version < "4.0" +beautifulsoup4==4.15.0 ; python_version >= "3.12" and python_version < "4.0" billiard==4.2.4 ; python_version >= "3.12" and python_version < "4.0" black==26.5.1 ; python_version >= "3.12" and python_version < "4.0" blinker==1.9.0 ; python_version >= "3.12" and python_version < "4.0" -cachetools==7.1.4 ; python_version >= "3.12" and python_version < "4.0" +cachetools==7.1.6 ; python_version >= "3.12" and python_version < "4.0" celery==5.6.3 ; python_version >= "3.12" and python_version < "4.0" -certifi==2026.6.17 ; python_version >= "3.12" and python_version < "4.0" -cffi==2.0.0 ; python_version >= "3.12" and python_version < "4.0" and (os_name == "nt" or platform_python_implementation != "PyPy") and (implementation_name != "pypy" or platform_python_implementation != "PyPy") +certifi==2026.7.22 ; python_version >= "3.12" and python_version < "4.0" +cffi==2.1.0 ; python_version >= "3.12" and python_version < "4.0" and (os_name == "nt" or platform_python_implementation != "PyPy") and (implementation_name != "pypy" or platform_python_implementation != "PyPy") cfgv==3.5.0 ; python_version >= "3.12" and python_version < "4.0" channels-redis==4.3.0 ; python_version >= "3.12" and python_version < "4.0" channels==4.3.2 ; python_version >= "3.12" and python_version < "4.0" -charset-normalizer==3.4.7 ; python_version >= "3.12" and python_version < "4.0" +charset-normalizer==3.4.9 ; python_version >= "3.12" and python_version < "4.0" click-didyoumean==0.3.1 ; python_version >= "3.12" and python_version < "4.0" click-plugins==1.1.1.2 ; python_version >= "3.12" and python_version < "4.0" click-repl==0.3.0 ; python_version >= "3.12" and python_version < "4.0" -click==8.3.3 ; python_version >= "3.12" and python_version < "4.0" +click==8.4.2 ; python_version >= "3.12" and python_version < "4.0" colorama==0.4.6 ; python_version >= "3.12" and python_version < "4.0" concurrent-log-handler==0.9.29 ; python_version >= "3.12" and python_version < "4.0" contourpy==1.3.3 ; python_version >= "3.12" and python_version < "4.0" cron-descriptor==1.4.5 ; python_version >= "3.12" and python_version < "4.0" cryptography==49.0.0 ; python_version >= "3.12" and python_version < "4.0" cycler==0.12.1 ; python_version >= "3.12" and python_version < "4.0" -debugpy==1.8.20 ; python_version >= "3.12" and python_version < "4.0" +debugpy==1.8.21 ; python_version >= "3.12" and python_version < "4.0" deptry==0.25.1 ; python_version >= "3.12" and python_version < "4.0" dill==0.4.1 ; python_version >= "3.12" and python_version < "4.0" -distlib==0.4.0 ; python_version >= "3.12" and python_version < "4.0" +distlib==0.4.3 ; python_version >= "3.12" and python_version < "4.0" distro==1.9.0 ; python_version >= "3.12" and python_version < "4.0" django-celery-beat==2.9.0 ; python_version >= "3.12" and python_version < "4.0" django-celery-results==2.6.0 ; python_version >= "3.12" and python_version < "4.0" @@ -46,111 +45,104 @@ django-encrypted-model-fields==0.6.5 ; python_version >= "3.12" and python_versi django-filter-stubs==0.1.3 ; python_version >= "3.12" and python_version < "4.0" django-filter==25.2 ; python_version >= "3.12" and python_version < "4.0" django-mcp-server==0.5.7 ; python_version >= "3.12" and python_version < "4.0" -django-simple-history==3.11.0 ; python_version >= "3.12" and python_version < "4.0" +django-simple-history==3.13.0 ; python_version >= "3.12" and python_version < "4.0" django-solo==2.5.1 ; python_version >= "3.12" and python_version < "4.0" -django-stubs-ext==6.0.3 ; python_version >= "3.12" and python_version < "4.0" -django-stubs==6.0.3 ; python_version >= "3.12" and python_version < "4.0" -django-timezone-field==7.2.1 ; python_version >= "3.12" and python_version < "4.0" +django-stubs-ext==6.0.7 ; python_version >= "3.12" and python_version < "4.0" +django-stubs==6.0.7 ; python_version >= "3.12" and python_version < "4.0" +django-timezone-field==7.2.2 ; python_version >= "3.12" and python_version < "4.0" django==6.0.7 ; python_version >= "3.12" and python_version < "4.0" djangorestframework-simplejwt==5.5.1 ; python_version >= "3.12" and python_version < "4.0" -djangorestframework-stubs==3.16.9 ; python_version >= "3.12" and python_version < "4.0" +djangorestframework-stubs==3.17.0 ; python_version >= "3.12" and python_version < "4.0" djangorestframework==3.17.1 ; python_version >= "3.12" and python_version < "4.0" docstring-parser==0.18.0 ; python_version >= "3.12" and python_version < "4.0" drf-spectacular==0.29.0 ; python_version >= "3.12" and python_version < "4.0" -dropbox==12.0.2 ; python_version >= "3.12" and python_version < "4.0" +dropbox==12.2.1 ; python_version >= "3.12" and python_version < "4.0" et-xmlfile==2.0.0 ; python_version >= "3.12" and python_version < "4.0" eval-type-backport==0.4.0 ; python_version >= "3.12" and python_version < "4.0" -faker==40.15.0 ; python_version >= "3.12" and python_version < "4.0" +faker==40.36.0 ; python_version >= "3.12" and python_version < "4.0" fastuuid==0.14.0 ; python_version >= "3.12" and python_version < "3.14" -filelock==3.29.0 ; python_version >= "3.12" and python_version < "4.0" +filelock==3.32.0 ; python_version >= "3.12" and python_version < "4.0" flake8-pyproject==1.2.4 ; python_version >= "3.12" and python_version < "4.0" flake8==7.3.0 ; python_version >= "3.12" and python_version < "4.0" -fonttools==4.62.1 ; python_version >= "3.12" and python_version < "4.0" +fonttools==4.63.0 ; python_version >= "3.12" and python_version < "4.0" freezegun==1.5.5 ; python_version >= "3.12" and python_version < "4.0" frozenlist==1.8.0 ; python_version >= "3.12" and python_version < "3.14" fsspec==2026.6.0 ; python_version >= "3.12" and python_version < "3.14" -google-ai-generativelanguage==0.6.15 ; python_version >= "3.12" and python_version < "4.0" -google-api-core==2.25.2 ; python_version >= "3.14" and python_version < "4.0" -google-api-core==2.30.3 ; python_version >= "3.12" and python_version < "3.14" +google-api-core==2.33.0 ; python_version >= "3.12" and python_version < "4.0" google-api-python-client-stubs==1.36.0 ; python_version >= "3.12" and python_version < "4.0" -google-api-python-client==2.195.0 ; python_version >= "3.12" and python_version < "4.0" -google-auth-httplib2==0.3.1 ; python_version >= "3.12" and python_version < "4.0" +google-api-python-client==2.198.0 ; python_version >= "3.12" and python_version < "4.0" +google-auth-httplib2==0.4.0 ; python_version >= "3.12" and python_version < "4.0" google-auth-stubs==0.3.0 ; python_version >= "3.12" and python_version < "4.0" -google-auth==2.53.0 ; python_version >= "3.12" and python_version < "4.0" -google-genai==2.10.0 ; python_version >= "3.12" and python_version < "4.0" -google-generativeai==0.8.6 ; python_version >= "3.12" and python_version < "4.0" -googleapis-common-protos==1.74.0 ; python_version >= "3.12" and python_version < "4.0" +google-auth==2.56.2 ; python_version >= "3.12" and python_version < "4.0" +google-genai==2.14.0 ; python_version >= "3.12" and python_version < "4.0" +googleapis-common-protos==1.75.0 ; python_version >= "3.12" and python_version < "4.0" grpc-stubs==1.53.0.6 ; python_version >= "3.12" and python_version < "4.0" -grpcio-status==1.71.2 ; python_version >= "3.12" and python_version < "4.0" -grpcio==1.80.0 ; python_version >= "3.12" and python_version < "4.0" +grpcio==1.83.0 ; python_version >= "3.12" and python_version < "4.0" gunicorn==26.0.0 ; python_version >= "3.12" and python_version < "4.0" h11==0.16.0 ; python_version >= "3.12" and python_version < "4.0" -hf-xet==1.4.3 ; python_version >= "3.12" and python_version < "3.14" and (platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "arm64" or platform_machine == "aarch64") -holidays==0.100 ; python_version >= "3.12" and python_version < "4.0" +hf-xet==1.5.2 ; python_version >= "3.12" and python_version < "3.14" and (platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "arm64" or platform_machine == "aarch64") +holidays==0.101 ; python_version >= "3.12" and python_version < "4.0" httpcore==1.0.9 ; python_version >= "3.12" and python_version < "4.0" -httplib2==0.31.2 ; python_version >= "3.12" and python_version < "4.0" +httplib2==0.32.0 ; python_version >= "3.12" and python_version < "4.0" httpx-sse==0.4.3 ; python_version >= "3.12" and python_version < "4.0" httpx==0.28.1 ; python_version >= "3.12" and python_version < "4.0" -huggingface-hub==1.13.0 ; python_version >= "3.12" and python_version < "3.14" +huggingface-hub==1.25.1 ; python_version >= "3.12" and python_version < "3.14" identify==2.6.19 ; python_version >= "3.12" and python_version < "4.0" idna==3.18 ; python_version >= "3.12" and python_version < "4.0" importlib-metadata==8.7.1 ; python_version >= "3.12" and python_version < "4.0" inflection==0.5.1 ; python_version >= "3.12" and python_version < "4.0" iniconfig==2.3.0 ; python_version >= "3.12" and python_version < "4.0" isort==8.0.1 ; python_version >= "3.12" and python_version < "4.0" -jinja2==3.1.6 ; python_version >= "3.12" and python_version < "3.14" -jiter==0.15.0 ; python_version >= "3.12" and python_version < "4.0" +jinja2==3.1.6 ; python_version >= "3.12" and python_version < "4.0" +jiter==0.16.0 ; python_version >= "3.12" and python_version < "4.0" jsonpath-python==1.1.6 ; python_version >= "3.12" and python_version < "4.0" jsonschema-specifications==2025.9.1 ; python_version >= "3.12" and python_version < "4.0" jsonschema==4.26.0 ; python_version >= "3.12" and python_version < "4.0" kiwisolver==1.5.0 ; python_version >= "3.12" and python_version < "4.0" kombu==5.6.2 ; python_version >= "3.12" and python_version < "4.0" levenshtein==0.27.3 ; python_version >= "3.12" and python_version < "4.0" -librt==0.11.0 ; python_version >= "3.12" and python_version < "4.0" and platform_python_implementation != "PyPy" -litellm==1.88.1 ; python_version >= "3.12" and python_version < "3.14" -lxml==6.1.0 ; python_version >= "3.12" and python_version < "4.0" -markdown-it-py==4.0.0 ; python_version >= "3.12" and python_version < "3.14" -markupsafe==3.0.3 ; python_version >= "3.12" and python_version < "3.14" -matplotlib==3.10.9 ; python_version >= "3.12" and python_version < "4.0" +librt==0.13.0 ; python_version >= "3.12" and python_version < "4.0" and platform_python_implementation != "PyPy" +litellm==1.93.0 ; python_version >= "3.12" and python_version < "3.14" +lxml==6.1.1 ; python_version >= "3.12" and python_version < "4.0" +markupsafe==3.0.3 ; python_version >= "3.12" and python_version < "4.0" +matplotlib==3.11.1 ; python_version >= "3.12" and python_version < "4.0" mccabe==0.7.0 ; python_version >= "3.12" and python_version < "4.0" mcp==1.28.1 ; python_version >= "3.12" and python_version < "4.0" -mdurl==0.1.2 ; python_version >= "3.12" and python_version < "3.14" -mistralai==2.6.0 ; python_version >= "3.12" and python_version < "4.0" +mistralai==2.7.2 ; python_version >= "3.12" and python_version < "4.0" msgpack==1.2.1 ; python_version >= "3.12" and python_version < "4.0" multidict==6.7.1 ; python_version >= "3.12" and python_version < "3.14" mypy-baseline==0.7.4 ; python_version >= "3.12" and python_version < "4.0" mypy-extensions==1.1.0 ; python_version >= "3.12" and python_version < "4.0" -mypy==2.1.0 ; python_version >= "3.12" and python_version < "4.0" +mypy==2.3.0 ; python_version >= "3.12" and python_version < "4.0" nicknames==1.0.1 ; python_version >= "3.12" and python_version < "4.0" nodeenv==1.10.0 ; python_version >= "3.12" and python_version < "4.0" nplus1==1.1.5 ; python_version >= "3.12" and python_version < "4.0" -numpy==2.4.4 ; python_version >= "3.12" and python_version < "4.0" -openai==2.24.0 ; python_version >= "3.12" and python_version < "3.14" +numpy==2.5.1 ; python_version >= "3.12" and python_version < "4.0" +openai==2.48.0 ; python_version >= "3.12" and python_version < "3.14" openpyxl==3.1.5 ; python_version >= "3.12" and python_version < "4.0" opentelemetry-api==1.39.1 ; python_version >= "3.12" and python_version < "4.0" opentelemetry-semantic-conventions==0.60b1 ; python_version >= "3.12" and python_version < "4.0" outcome==1.3.0.post0 ; python_version >= "3.12" and python_version < "4.0" packaging==26.2 ; python_version >= "3.12" and python_version < "4.0" pandas-stubs==3.0.3.260530 ; python_version >= "3.12" and python_version < "4.0" -pandas==3.0.2 ; python_version >= "3.12" and python_version < "4.0" +pandas==3.0.5 ; python_version >= "3.12" and python_version < "4.0" pathspec==1.1.1 ; python_version >= "3.12" and python_version < "4.0" pdf2image==1.17.0 ; python_version >= "3.12" and python_version < "4.0" -pdfminer-six==20251230 ; python_version >= "3.12" and python_version < "4.0" -pdfplumber==0.11.9 ; python_version >= "3.12" and python_version < "4.0" -pillow==12.2.0 ; python_version >= "3.12" and python_version < "4.0" -platformdirs==4.9.6 ; python_version >= "3.12" and python_version < "4.0" +pdfminer-six==20260107 ; python_version >= "3.12" and python_version < "4.0" +pdfplumber==0.11.10 ; python_version >= "3.12" and python_version < "4.0" +pillow==12.3.0 ; python_version >= "3.12" and python_version < "4.0" +platformdirs==4.11.0 ; python_version >= "3.12" and python_version < "4.0" pluggy==1.6.0 ; python_version >= "3.12" and python_version < "4.0" -ply==3.11 ; python_version >= "3.12" and python_version < "4.0" portalocker==3.2.0 ; python_version >= "3.12" and python_version < "4.0" -pre-commit==4.6.0 ; python_version >= "3.12" and python_version < "4.0" -prompt-toolkit==3.0.52 ; python_version >= "3.12" and python_version < "4.0" -propcache==0.4.1 ; python_version >= "3.12" and python_version < "3.14" -proto-plus==1.27.2 ; python_version >= "3.12" and python_version < "4.0" -protobuf==5.29.6 ; python_version >= "3.12" and python_version < "4.0" +pre-commit==4.6.1 ; python_version >= "3.12" and python_version < "4.0" +prompt-toolkit==3.0.53 ; python_version >= "3.12" and python_version < "4.0" +propcache==0.5.2 ; python_version >= "3.12" and python_version < "3.14" +proto-plus==1.28.2 ; python_version >= "3.12" and python_version < "4.0" +protobuf==7.35.1 ; python_version >= "3.12" and python_version < "4.0" psycopg-binary==3.3.4 ; python_version >= "3.12" and python_version < "4.0" and implementation_name != "pypy" psycopg==3.3.4 ; python_version >= "3.12" and python_version < "4.0" pyasn1-modules==0.4.2 ; python_version >= "3.12" and python_version < "4.0" -pyasn1==0.6.3 ; python_version >= "3.12" and python_version < "4.0" +pyasn1==0.6.4 ; python_version >= "3.12" and python_version < "4.0" pycodestyle==2.14.0 ; python_version >= "3.12" and python_version < "4.0" pycparser==3.0 ; python_version >= "3.12" and python_version < "4.0" and (platform_python_implementation != "PyPy" or os_name == "nt") and (platform_python_implementation != "PyPy" or implementation_name != "pypy" and implementation_name != "PyPy") and implementation_name != "PyPy" pydantic-core==2.46.4 ; python_version >= "3.12" and python_version < "4.0" @@ -165,79 +157,76 @@ pylint==4.0.6 ; python_version >= "3.12" and python_version < "4.0" pyngrok==7.5.1 ; python_version >= "3.12" and python_version < "4.0" pyparsing==3.3.2 ; python_version >= "3.12" and python_version < "4.0" pypdf==6.14.2 ; python_version >= "3.12" and python_version < "4.0" -pypdfium2==5.7.1 ; python_version >= "3.12" and python_version < "4.0" -pyproject-api==1.10.1 ; python_version >= "3.12" and python_version < "4.0" +pypdfium2==5.12.1 ; python_version >= "3.12" and python_version < "4.0" +pyproject-api==1.11.0 ; python_version >= "3.12" and python_version < "4.0" pysocks==1.7.1 ; python_version >= "3.12" and python_version < "4.0" pytest-django==4.12.0 ; python_version >= "3.12" and python_version < "4.0" -pytest==9.0.3 ; python_version >= "3.12" and python_version < "4.0" +pytest==9.1.1 ; python_version >= "3.12" and python_version < "4.0" python-crontab==3.3.0 ; python_version >= "3.12" and python_version < "4.0" python-dateutil==2.9.0.post0 ; python_version >= "3.12" and python_version < "4.0" -python-discovery==1.4.2 ; python_version >= "3.12" and python_version < "4.0" +python-discovery==1.5.0 ; python_version >= "3.12" and python_version < "4.0" python-docx==1.2.0 ; python_version >= "3.12" and python_version < "4.0" python-dotenv==1.2.2 ; python_version >= "3.12" and python_version < "4.0" python-levenshtein==0.27.3 ; python_version >= "3.12" and python_version < "4.0" python-multipart==0.0.32 ; python_version >= "3.12" and python_version < "4.0" python-stdnum==2.2 ; python_version >= "3.12" and python_version < "4.0" pytokens==0.4.1 ; python_version >= "3.12" and python_version < "4.0" -pytz==2026.2 ; python_version >= "3.12" and python_version < "4.0" -pywin32==311 ; python_version >= "3.12" and python_version < "4.0" and (sys_platform == "win32" or platform_system == "Windows") +pytz==2026.3.post1 ; python_version >= "3.12" and python_version < "4.0" +pywin32==312 ; python_version >= "3.12" and python_version < "4.0" and (sys_platform == "win32" or platform_system == "Windows") pyyaml==6.0.3 ; python_version >= "3.12" and python_version < "4.0" rapidfuzz==3.14.5 ; python_version >= "3.12" and python_version < "4.0" -redis==7.4.0 ; python_version >= "3.12" and python_version < "4.0" +redis==8.0.1 ; python_version >= "3.12" and python_version < "4.0" referencing==0.37.0 ; python_version >= "3.12" and python_version < "4.0" -regex==2026.4.4 ; python_version >= "3.12" and python_version < "3.14" +regex==2026.7.19 ; python_version >= "3.12" and python_version < "3.14" reportlab==5.0.0 ; python_version >= "3.12" and python_version < "4.0" requests==2.34.2 ; python_version >= "3.12" and python_version < "4.0" -requirements-parser==0.13.0 ; python_version >= "3.12" and python_version < "4.0" -rich==15.0.0 ; python_version >= "3.12" and python_version < "3.14" -rpds-py==0.30.0 ; python_version >= "3.12" and python_version < "4.0" -ruff==0.15.12 ; python_version >= "3.12" and python_version < "4.0" -selenium==4.43.0 ; python_version >= "3.12" and python_version < "4.0" -setuptools==82.0.1 ; python_version >= "3.12" and python_version < "4.0" -shellingham==1.5.4 ; python_version >= "3.12" and python_version < "3.14" +requirements-parser==0.13.1 ; python_version >= "3.12" and python_version < "4.0" +rpds-py==2026.6.3 ; python_version >= "3.12" and python_version < "4.0" +ruff==0.15.22 ; python_version >= "3.12" and python_version < "4.0" +selenium==4.46.0 ; python_version >= "3.12" and python_version < "4.0" +setuptools==83.0.0 ; python_version >= "3.12" and python_version < "4.0" six==1.17.0 ; python_version >= "3.12" and python_version < "4.0" sniffio==1.3.1 ; python_version >= "3.12" and python_version < "4.0" sortedcontainers==2.4.0 ; python_version >= "3.12" and python_version < "4.0" -soupsieve==2.8.4 ; python_version >= "3.12" and python_version < "4.0" +soupsieve==2.9.1 ; python_version >= "3.12" and python_version < "4.0" sqlparse==0.5.5 ; python_version >= "3.12" and python_version < "4.0" -sse-starlette==3.4.1 ; python_version >= "3.12" and python_version < "4.0" +sse-starlette==3.4.6 ; python_version >= "3.12" and python_version < "4.0" starlette==1.3.1 ; python_version >= "3.12" and python_version < "4.0" -stone==3.3.1 ; python_version >= "3.12" and python_version < "4.0" +stone==3.5.3 ; python_version >= "3.12" and python_version < "4.0" tabulate==0.10.0 ; python_version >= "3.12" and python_version < "4.0" tenacity==9.1.4 ; python_version >= "3.12" and python_version < "4.0" thefuzz==0.22.1 ; python_version >= "3.12" and python_version < "4.0" -tiktoken==0.12.0 ; python_version >= "3.12" and python_version < "3.14" -tokenizers==0.22.2 ; python_version >= "3.12" and python_version < "3.14" +tiktoken==0.13.0 ; python_version >= "3.12" and python_version < "3.14" +tokenizers==0.23.1 ; python_version >= "3.12" and python_version < "3.14" toml==0.10.2 ; python_version >= "3.12" and python_version < "4.0" tomli-w==1.2.0 ; python_version >= "3.12" and python_version < "4.0" tomli==2.4.1 ; python_version >= "3.12" and python_version < "3.15" -tomlkit==0.15.0 ; python_version >= "3.12" and python_version < "4.0" -tox==4.53.1 ; python_version >= "3.12" and python_version < "4.0" -tqdm==4.67.3 ; python_version >= "3.12" and python_version < "4.0" +tomlkit==0.15.1 ; python_version >= "3.12" and python_version < "4.0" +tox==4.58.0 ; python_version >= "3.12" and python_version < "4.0" +tqdm==4.69.1 ; python_version >= "3.12" and python_version < "3.14" trio-websocket==0.12.2 ; python_version >= "3.12" and python_version < "4.0" trio==0.33.0 ; python_version >= "3.12" and python_version < "4.0" -typer==0.23.1 ; python_version >= "3.12" and python_version < "3.14" -types-httplib2==0.31.2.20260408 ; python_version >= "3.12" and python_version < "4.0" +types-httplib2==0.32.0.20260720 ; python_version >= "3.12" and python_version < "4.0" types-jsonschema==4.26.0.20260518 ; python_version >= "3.12" and python_version < "4.0" -types-python-dateutil==2.9.0.20260408 ; python_version >= "3.12" and python_version < "4.0" -types-pytz==2026.1.1.20260408 ; python_version >= "3.12" and python_version < "4.0" -types-pyyaml==6.0.12.20260408 ; python_version >= "3.12" and python_version < "4.0" -types-reportlab==4.5.1.20260521 ; python_version >= "3.12" and python_version < "4.0" -types-requests==2.33.0.20260503 ; python_version >= "3.12" and python_version < "4.0" -typing-extensions==4.15.0 ; python_version >= "3.12" and python_version < "4.0" +types-python-dateutil==2.9.0.20260716 ; python_version >= "3.12" and python_version < "4.0" +types-pytz==2026.3.1.20260727 ; python_version >= "3.12" and python_version < "4.0" +types-pyyaml==6.0.12.20260724 ; python_version >= "3.12" and python_version < "4.0" +types-reportlab==4.5.1.20260724 ; python_version >= "3.12" and python_version < "4.0" +types-requests==2.33.0.20260712 ; python_version >= "3.12" and python_version < "4.0" +typing-extensions==4.16.0 ; python_version >= "3.12" and python_version < "4.0" typing-inspection==0.4.2 ; python_version >= "3.12" and python_version < "4.0" -tzdata==2026.2 ; python_version >= "3.12" and python_version < "4.0" -tzlocal==5.3.1 ; python_version >= "3.12" and python_version < "4.0" +tzdata==2026.3 ; python_version >= "3.12" and python_version < "4.0" +tzlocal==5.4.4 ; python_version >= "3.12" and python_version < "4.0" uritemplate==4.2.0 ; python_version >= "3.12" and python_version < "4.0" urllib3==2.7.0 ; python_version >= "3.12" and python_version < "4.0" -uvicorn==0.46.0 ; python_version >= "3.12" and python_version < "4.0" and sys_platform != "emscripten" +uvicorn==0.51.0 ; python_version >= "3.12" and python_version < "4.0" and sys_platform != "emscripten" vine==5.1.0 ; python_version >= "3.12" and python_version < "4.0" -virtualenv==21.5.1 ; python_version >= "3.12" and python_version < "4.0" +virtualenv==21.7.0 ; python_version >= "3.12" and python_version < "4.0" vulture==2.16 ; python_version >= "3.12" and python_version < "4.0" -wcwidth==0.7.0 ; python_version >= "3.12" and python_version < "4.0" +wcwidth==0.8.2 ; python_version >= "3.12" and python_version < "4.0" websocket-client==1.9.0 ; python_version >= "3.12" and python_version < "4.0" -websockets==16.0 ; python_version >= "3.12" and python_version < "4.0" +websockets==16.1.1 ; python_version >= "3.12" and python_version < "4.0" wsproto==1.3.2 ; python_version >= "3.12" and python_version < "4.0" -xero-python==14.0.0 ; python_version >= "3.12" and python_version < "4.0" -yarl==1.23.0 ; python_version >= "3.12" and python_version < "3.14" -zipp==3.23.1 ; python_version >= "3.12" and python_version < "4.0" +xero-python==15.0.0 ; python_version >= "3.12" and python_version < "4.0" +yarl==1.24.5 ; python_version >= "3.12" and python_version < "3.14" +zipp==4.1.0 ; python_version >= "3.12" and python_version < "4.0" From 544e5bb399abc16d8882081b11e680f9c3f4a479 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Tue, 28 Jul 2026 09:15:44 +1200 Subject: [PATCH 02/39] chore(deps): upgrade past declared bounds; record the pinning policy Version constraints in this repo record the newest version that passed testing, not a known incompatibility, so a release sweep must ignore them and re-test at latest. The first pass respected the declared bounds and so could only move within the previous sweep's ceiling. This pass widens them. Backend, previously capped by our own carets: django-filter 25 -> 26, pyngrok 7 -> 8, drf-spectacular 0.29 -> 0.30, anthropic 0.120.0, ruff 0.16.0, google-api-python-client-stubs 1.39.0. Frontend: pinia 3 -> 4, pdf-vue3 1 -> 2, @types/node 25 -> 26, prettier 3.8.3 -> 3.9.6 (reformats 8 files). drf-spectacular 0.30 emits oneOf [format, {maxLength: 0}] for format-constrained fields with allow_blank=True, which is a more honest description of the contract: Company.email is EmailField(null=True, blank=True) and 45 rows hold "". The regenerated client therefore relaxes those fields from z.string().email() to a union. The previous schema was the inaccurate one -- it would have rejected data the backend legitimately returns. Record the policy as ADR 0033 so the next sweep does not mistake a test record for a compatibility bound. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Qo7UkADwmj73int333bEnV --- CLAUDE.md | 1 + ...sion-constraints-record-tested-versions.md | 25 ++ docs/adr/README.md | 1 + frontend/package-lock.json | 302 ++++++++---------- frontend/package.json | 8 +- frontend/schema.yml | 276 ++++++++++------ frontend/src/api/generated/api.ts | 68 ++-- .../src/components/CreateCompanyModal.vue | 3 +- .../src/components/TaskExecutionsModal.vue | 3 +- .../components/admin/errors/ErrorDialog.vue | 3 +- .../safety-wizard/SafetyWizardModal.vue | 6 +- .../reports/data-quality/archived-jobs.vue | 6 +- .../data-quality/duplicate-identities.vue | 3 +- frontend/src/pages/reports/rdti-spend.vue | 8 +- frontend/src/types/processDocument.types.ts | 8 +- poetry.lock | 83 ++--- pyproject.toml | 12 +- requirements.txt | 14 +- 18 files changed, 449 insertions(+), 381 deletions(-) create mode 100644 docs/adr/0033-version-constraints-record-tested-versions.md diff --git a/CLAUDE.md b/CLAUDE.md index 2f4a35543..609cdc196 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,6 +12,7 @@ Major architectural decisions are recorded in [`docs/adr/`](docs/adr/README.md). - **0020** — Backend owns data, calculations, and external systems; frontend owns presentation. The boundary is the kind of value, not the layer of code. - **0021** — Frontend reads/writes the API only via the generated client; raw `fetch`/`axios` is forbidden. - **0032** — Less code is better: prefer a maintained library over a homegrown implementation. Writing your own for something a library provides needs an explicit, recorded reason it isn't a library. +- **0033** — A version constraint records the newest version that passed testing, never a known incompatibility. Release sweeps ignore the declared bounds and re-test at latest; a version stays behind only when upstream metadata pins it or a gate fails. CLAUDE.md is the operational layer (session behaviour, code-style gotchas, architecture facts). ADRs explain *why*. diff --git a/docs/adr/0033-version-constraints-record-tested-versions.md b/docs/adr/0033-version-constraints-record-tested-versions.md new file mode 100644 index 000000000..72e384468 --- /dev/null +++ b/docs/adr/0033-version-constraints-record-tested-versions.md @@ -0,0 +1,25 @@ +# 0033 — Version constraints record what passed testing, not what is compatible + +Every declared dependency bound is a record of the newest version that passed our tests, so a release sweep ignores the bounds and re-tests at latest. + +## Problem + +`pillow = "^12.1.1"`, `holidays = ">=0.93,<0.101"`, and `prettier: "3.8.3"` all look like compatibility limits — as though 13, 0.101, and 3.9 were tried and rejected. They were not. Each records the newest version available the last time we swept dependencies. Reading them as compatibility boundaries makes an upgrade look risky when nobody has ever tested the newer version, and a sweep that respects them can only ever move within the last sweep's ceiling. + +## Decision + +Treat every version constraint as a test record, never as evidence of incompatibility. During a release dependency sweep, ignore the declared bounds: widen each constraint to the newest published version, re-lock, and run the gates. A version stays behind latest only when something external forces it — an upstream package's own published metadata pins it, or the upgrade fails a gate. Record that reason in the PR. When a constraint is widened and the gates pass, the new bound becomes the updated test record. + +## Why + +The bound and the reason for the bound are different facts, and only the bound is written down. Once they are conflated, dependency debt compounds silently: each sweep respects the previous sweep's ceiling, so majors accumulate untested behind carets that were never a judgement about anything. Testing is the only thing that produces real evidence, and it is cheap and automated here — so the honest default is to move everything to latest and let the gates speak. That also keeps the expensive signal, an actual failure, distinguishable from the absence of signal. + +## Alternatives considered + +- **Conservative carets, upgrade on demand:** the common default — take patches automatically, majors only when a feature needs one. Sensible where upgrades are risky or the test suite is thin. Here it guarantees that majors are only ever discovered under deadline, bundled with the feature that forced them, which is the worst time to debug a breaking change. +- **Pin everything exactly and never sweep:** maximum reproducibility, and correct for a system that must not change. It converts every eventual upgrade into an archaeology exercise across years of releases at once, and leaves security advisories unpatched by default. +- **Automated per-PR bumps only (dependabot merged as it opens them):** keeps the lag near zero without a sweep. It cannot resolve interlocked upgrades — the cases where a bump is only possible alongside another package's — which is exactly where the debt collects. + +## Consequences + +Dependency lag stays near zero and majors surface one at a time, on a schedule, with the whole test suite as the arbiter. The cost is a real testing burden every release, and sweeps that occasionally have to back a version out. A constraint below latest becomes meaningful: it means something genuinely blocked, and the PR says what. diff --git a/docs/adr/README.md b/docs/adr/README.md index 927f4cb71..71ceea8c1 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -42,3 +42,4 @@ See [`_template.md`](_template.md). Copy, renumber, fill in. | 0030 | First-class People and Company links | | 0031 | One logging gate: the debug library with namespaces | | 0032 | Less code is better: prefer libraries over homegrown implementations | +| 0033 | Version constraints record what passed testing, not what is compatible | diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 8c0199071..ab327f4b4 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -36,8 +36,8 @@ "lodash-es": "^4.18.1", "lucide-vue-next": "^1.0.0", "openapi-zod-client": "^1.18.3", - "pdf-vue3": "^1.0.12", - "pinia": "^3.0.1", + "pdf-vue3": "^2.0.1", + "pinia": "^4.0.2", "qs": "^6.15.2", "quill": "^2.0.3", "reka-ui": "^2.8.2", @@ -62,7 +62,7 @@ "@types/debug": "^4.1.13", "@types/dompurify": "^3.2.0", "@types/js-cookie": "^3.0.6", - "@types/node": "^25.9.3", + "@types/node": "^26.1.2", "@typescript-eslint/eslint-plugin": "^8.59.4", "@typescript-eslint/parser": "^8.64.0", "@vitejs/plugin-vue": "^6.0.8", @@ -79,7 +79,7 @@ "jiti": "^2.4.2", "lint-staged": "^17.0.3", "npm-run-all2": "^8.0.4", - "prettier": "3.8.3", + "prettier": "3.9.6", "puppeteer": "^25.0.2", "tsx": "^4.21.0", "typescript": "~6.0.3", @@ -1576,6 +1576,39 @@ } } }, + "node_modules/@kodeglot/vue-calendar/node_modules/@vue/devtools-api": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.10.tgz", + "integrity": "sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.10" + } + }, + "node_modules/@kodeglot/vue-calendar/node_modules/@vue/devtools-kit": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.10.tgz", + "integrity": "sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.10", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@kodeglot/vue-calendar/node_modules/@vue/devtools-shared": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.10.tgz", + "integrity": "sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, "node_modules/@kodeglot/vue-calendar/node_modules/date-fns": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", @@ -1586,6 +1619,33 @@ "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/@kodeglot/vue-calendar/node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/@kodeglot/vue-calendar/node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@kodeglot/vue-calendar/node_modules/uuid": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", @@ -3461,12 +3521,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.9.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.5.tgz", - "integrity": "sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==", + "version": "26.1.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.2.tgz", + "integrity": "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==", "license": "MIT", "dependencies": { - "undici-types": ">=7.24.0 <7.24.7" + "undici-types": "~8.3.0" } }, "node_modules/@types/parse-json": { @@ -4294,12 +4354,12 @@ } }, "node_modules/@vue/devtools-api": { - "version": "7.7.10", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.10.tgz", - "integrity": "sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.2.1.tgz", + "integrity": "sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==", "license": "MIT", "dependencies": { - "@vue/devtools-kit": "^7.7.10" + "@vue/devtools-kit": "^8.2.1" } }, "node_modules/@vue/devtools-core": { @@ -4316,11 +4376,10 @@ "vue": "^3.0.0" } }, - "node_modules/@vue/devtools-core/node_modules/@vue/devtools-kit": { + "node_modules/@vue/devtools-kit": { "version": "8.2.1", "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", - "dev": true, "license": "MIT", "dependencies": { "@vue/devtools-shared": "^8.2.1", @@ -4329,44 +4388,12 @@ "perfect-debounce": "^2.0.0" } }, - "node_modules/@vue/devtools-core/node_modules/@vue/devtools-shared": { + "node_modules/@vue/devtools-shared": { "version": "8.2.1", "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", - "dev": true, "license": "MIT" }, - "node_modules/@vue/devtools-core/node_modules/perfect-debounce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", - "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vue/devtools-kit": { - "version": "7.7.10", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.10.tgz", - "integrity": "sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==", - "license": "MIT", - "dependencies": { - "@vue/devtools-shared": "^7.7.10", - "birpc": "^2.3.0", - "hookable": "^5.5.3", - "mitt": "^3.0.1", - "perfect-debounce": "^1.0.0", - "speakingurl": "^14.0.1", - "superjson": "^2.2.2" - } - }, - "node_modules/@vue/devtools-shared": { - "version": "7.7.10", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.10.tgz", - "integrity": "sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==", - "license": "MIT", - "dependencies": { - "rfdc": "^1.4.1" - } - }, "node_modules/@vue/eslint-config-prettier": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-10.2.0.tgz", @@ -10485,15 +10512,15 @@ } }, "node_modules/pdf-vue3": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/pdf-vue3/-/pdf-vue3-1.0.12.tgz", - "integrity": "sha512-7SMTx1RfRwdc+2WPniDzqM8MxJLqTNNzdyV0SeQTxeRLJGndb5Wv/fz5afO13oBSIvvaqcbZ/S3gF+XjqkSb9g==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pdf-vue3/-/pdf-vue3-2.0.1.tgz", + "integrity": "sha512-1hH48DEmJhSsHo27IFVp0aj97gkI1oe1Fvk6Xz1i8hNNkT6e2QrZ9fCmiVsL+I6bDCWL/e3LvskRTPRlflH5tw==", "license": "MIT" }, "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", "license": "MIT" }, "node_modules/picocolors": { @@ -10528,21 +10555,25 @@ } }, "node_modules/pinia": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", - "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-4.0.2.tgz", + "integrity": "sha512-yKVVA7bSj5oRZFp/Ab9wLlmyb5gPUYEiIm4ryiWTe/xe7PtkRdMVOp1X1ggvq0c6Uj7Q0Du1HnV2mtAwM0Ks1g==", "license": "MIT", "dependencies": { - "@vue/devtools-api": "^7.7.7" + "nostics": "^1.1.4" }, "funding": { "url": "https://github.com/sponsors/posva" }, "peerDependencies": { - "typescript": ">=4.5.0", + "@vue/devtools-api": "^8.1.5", + "typescript": ">=5.6.0", "vue": "^3.5.11" }, "peerDependenciesMeta": { + "@vue/devtools-api": { + "optional": false + }, "typescript": { "optional": true } @@ -10663,9 +10694,9 @@ } }, "node_modules/prettier": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", - "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", "dev": true, "license": "MIT", "bin": { @@ -11997,9 +12028,9 @@ } }, "node_modules/undici-types": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", - "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", "license": "MIT" }, "node_modules/unist-util-is": { @@ -12352,6 +12383,45 @@ "vue": "^3.4.26" } }, + "node_modules/vee-validate/node_modules/@vue/devtools-api": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.10.tgz", + "integrity": "sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.10" + } + }, + "node_modules/vee-validate/node_modules/@vue/devtools-kit": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.10.tgz", + "integrity": "sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.10", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/vee-validate/node_modules/@vue/devtools-shared": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.10.tgz", + "integrity": "sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/vee-validate/node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -12531,13 +12601,6 @@ } } }, - "node_modules/vite-plugin-inspect/node_modules/perfect-debounce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", - "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", - "dev": true, - "license": "MIT" - }, "node_modules/vite-plugin-vue-devtools": { "version": "8.2.1", "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.2.1.tgz", @@ -12559,33 +12622,6 @@ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-kit": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", - "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-shared": "^8.2.1", - "birpc": "^2.6.1", - "hookable": "^5.5.3", - "perfect-debounce": "^2.0.0" - } - }, - "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-shared": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", - "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", - "dev": true, - "license": "MIT" - }, - "node_modules/vite-plugin-vue-devtools/node_modules/perfect-debounce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", - "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", - "dev": true, - "license": "MIT" - }, "node_modules/vite-plugin-vue-inspector": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-6.0.0.tgz", @@ -12668,36 +12704,6 @@ } } }, - "node_modules/vitepress/node_modules/@vue/devtools-api": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.2.1.tgz", - "integrity": "sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-kit": "^8.2.1" - } - }, - "node_modules/vitepress/node_modules/@vue/devtools-kit": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", - "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-shared": "^8.2.1", - "birpc": "^2.6.1", - "hookable": "^5.5.3", - "perfect-debounce": "^2.0.0" - } - }, - "node_modules/vitepress/node_modules/@vue/devtools-shared": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", - "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", - "dev": true, - "license": "MIT" - }, "node_modules/vitepress/node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -12713,13 +12719,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/vitepress/node_modules/perfect-debounce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", - "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", - "dev": true, - "license": "MIT" - }, "node_modules/vitepress/node_modules/vite": { "version": "7.3.6", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", @@ -13093,39 +13092,6 @@ "node": "^22.18.0 || >=24.11.0" } }, - "node_modules/vue-router/node_modules/@vue/devtools-api": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.2.1.tgz", - "integrity": "sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==", - "license": "MIT", - "dependencies": { - "@vue/devtools-kit": "^8.2.1" - } - }, - "node_modules/vue-router/node_modules/@vue/devtools-kit": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", - "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", - "license": "MIT", - "dependencies": { - "@vue/devtools-shared": "^8.2.1", - "birpc": "^2.6.1", - "hookable": "^5.5.3", - "perfect-debounce": "^2.0.0" - } - }, - "node_modules/vue-router/node_modules/@vue/devtools-shared": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", - "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", - "license": "MIT" - }, - "node_modules/vue-router/node_modules/perfect-debounce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", - "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", - "license": "MIT" - }, "node_modules/vue-sonner": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/vue-sonner/-/vue-sonner-2.0.9.tgz", diff --git a/frontend/package.json b/frontend/package.json index 0e5a8f350..b84a07893 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -57,8 +57,8 @@ "lodash-es": "^4.18.1", "lucide-vue-next": "^1.0.0", "openapi-zod-client": "^1.18.3", - "pdf-vue3": "^1.0.12", - "pinia": "^3.0.1", + "pdf-vue3": "^2.0.1", + "pinia": "^4.0.2", "qs": "^6.15.2", "quill": "^2.0.3", "reka-ui": "^2.8.2", @@ -83,7 +83,7 @@ "@types/debug": "^4.1.13", "@types/dompurify": "^3.2.0", "@types/js-cookie": "^3.0.6", - "@types/node": "^25.9.3", + "@types/node": "^26.1.2", "@typescript-eslint/eslint-plugin": "^8.59.4", "@typescript-eslint/parser": "^8.64.0", "@vitejs/plugin-vue": "^6.0.8", @@ -100,7 +100,7 @@ "jiti": "^2.4.2", "lint-staged": "^17.0.3", "npm-run-all2": "^8.0.4", - "prettier": "3.8.3", + "prettier": "3.9.6", "puppeteer": "^25.0.2", "tsx": "^4.21.0", "typescript": "~6.0.3", diff --git a/frontend/schema.yml b/frontend/schema.yml index 6bf59f665..b55244d49 100644 --- a/frontend/schema.yml +++ b/frontend/schema.yml @@ -10751,9 +10751,12 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email nullable: true + oneOf: + - type: string + format: email + - type: string + maxLength: 0 phone: type: string nullable: true @@ -10870,22 +10873,28 @@ components: description: Prefix for purchase order numbers (e.g., PO-, JO-) maxLength: 10 master_quote_template_url: - type: string - format: uri nullable: true description: URL to the master Google Sheets quote template - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 master_quote_template_id: type: string nullable: true description: Google Sheets ID for the quote template maxLength: 100 gdrive_quotes_folder_url: - type: string - format: uri nullable: true description: URL to the Google Drive folder for storing quotes - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 gdrive_quotes_folder_id: type: string nullable: true @@ -11047,17 +11056,23 @@ components: description: Country name maxLength: 100 company_email: - type: string - format: email nullable: true description: Company contact email address - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 company_url: - type: string - format: uri nullable: true description: Company website URL - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 test_company_name: type: string nullable: true @@ -11257,22 +11272,28 @@ components: description: Prefix for purchase order numbers (e.g., PO-, JO-) maxLength: 10 master_quote_template_url: - type: string - format: uri nullable: true description: URL to the master Google Sheets quote template - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 master_quote_template_id: type: string nullable: true description: Google Sheets ID for the quote template maxLength: 100 gdrive_quotes_folder_url: - type: string - format: uri nullable: true description: URL to the Google Drive folder for storing quotes - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 gdrive_quotes_folder_id: type: string nullable: true @@ -11429,17 +11450,23 @@ components: description: Country name maxLength: 100 company_email: - type: string - format: email nullable: true description: Company contact email address - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 company_url: - type: string - format: uri nullable: true description: Company website URL - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 test_company_name: type: string nullable: true @@ -11773,9 +11800,12 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email nullable: true + oneOf: + - type: string + format: email + - type: string + maxLength: 0 phone: type: string nullable: true @@ -11862,8 +11892,11 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email + oneOf: + - type: string + format: email + - type: string + maxLength: 0 phone: type: string nullable: true @@ -13769,10 +13802,13 @@ components: type: number format: double online_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 required: - amount_due - date @@ -16319,8 +16355,11 @@ components: description: Serializer for link quote sheet request data. properties: template_url: - type: string - format: uri + oneOf: + - type: string + format: uri + - type: string + maxLength: 0 LinkQuoteSheetResponse: type: object description: Serializer for link quote sheet response. @@ -17132,22 +17171,28 @@ components: description: Prefix for purchase order numbers (e.g., PO-, JO-) maxLength: 10 master_quote_template_url: - type: string - format: uri nullable: true description: URL to the master Google Sheets quote template - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 master_quote_template_id: type: string nullable: true description: Google Sheets ID for the quote template maxLength: 100 gdrive_quotes_folder_url: - type: string - format: uri nullable: true description: URL to the Google Drive folder for storing quotes - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 gdrive_quotes_folder_id: type: string nullable: true @@ -17304,17 +17349,23 @@ components: description: Country name maxLength: 100 company_email: - type: string - format: email nullable: true description: Company contact email address - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 company_url: - type: string - format: uri nullable: true description: Company website URL - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 test_company_name: type: string nullable: true @@ -17409,8 +17460,11 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email + oneOf: + - type: string + format: email + - type: string + maxLength: 0 phone: type: string nullable: true @@ -17681,10 +17735,13 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 PatchedPhoneEndpointRequest: type: object properties: @@ -17716,10 +17773,13 @@ components: recording_deletion_enabled: type: boolean base_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 username: type: string writeOnly: true @@ -18539,10 +18599,13 @@ components: type: string maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 is_active: type: boolean created_at: @@ -18582,10 +18645,13 @@ components: type: string maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 PersonIdentityUpdateRequest: type: object properties: @@ -18594,10 +18660,13 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 PersonSummary: type: object properties: @@ -18609,10 +18678,13 @@ components: type: string maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 is_active: type: boolean primary_phone: @@ -19083,10 +19155,13 @@ components: recording_deletion_enabled: type: boolean base_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 has_username: type: boolean readOnly: true @@ -19367,10 +19442,13 @@ components: description: Work site location maxLength: 500 google_doc_url: - type: string - format: uri description: URL to edit the document in Google Docs - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 job_number: type: string readOnly: true @@ -19669,10 +19747,13 @@ components: format: date nullable: true online_url: - type: string - format: uri nullable: true - maxLength: 500 + oneOf: + - type: string + format: uri + maxLength: 500 + - type: string + maxLength: 0 xero_id: type: string format: uuid @@ -20213,10 +20294,13 @@ components: type: number format: double online_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 required: - date - id @@ -20337,10 +20421,13 @@ components: description: Google Drive file ID maxLength: 100 sheet_url: - type: string - format: uri nullable: true - maxLength: 500 + oneOf: + - type: string + format: uri + maxLength: 500 + - type: string + maxLength: 0 tab: type: string nullable: true @@ -24257,9 +24344,12 @@ components: format: uuid description: The Xero UUID of the created/modified document. online_url: - type: string - format: uri description: Direct link to the document in Xero. + oneOf: + - type: string + format: uri + - type: string + maxLength: 0 messages: type: array items: @@ -24371,10 +24461,13 @@ components: status: $ref: '#/components/schemas/InvoiceStatusEnum' online_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 required: - number XeroInvoiceCreateModeEnum: @@ -24503,10 +24596,13 @@ components: status: $ref: '#/components/schemas/QuoteStatusEnum' online_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 XeroQuoteCreateRequest: type: object description: |- diff --git a/frontend/src/api/generated/api.ts b/frontend/src/api/generated/api.ts index 3a4c76662..fd14d6139 100644 --- a/frontend/src/api/generated/api.ts +++ b/frontend/src/api/generated/api.ts @@ -676,7 +676,7 @@ const CompanyPerson = z.object({ }) const CompanyPersonCreateRequest = z.object({ name: z.string().min(1).max(255), - email: z.string().email().nullish(), + email: z.union([z.string(), z.string()]).nullish(), phone: z.string().nullish(), position: z.string().max(255).nullish(), notes: z.string().nullish(), @@ -730,7 +730,7 @@ const SupplierSearchAliasCreateRequest = z.object({ const CompanyUpdateRequest = z .object({ name: z.string().min(1).max(255), - email: z.string().email(), + email: z.union([z.string(), z.string()]), phone: z.string().nullable(), address: z.string(), is_account_customer: z.boolean(), @@ -745,7 +745,7 @@ const CompanyUpdateResponse = z.object({ const PatchedCompanyUpdateRequest = z .object({ name: z.string().min(1).max(255), - email: z.string().email(), + email: z.union([z.string(), z.string()]), phone: z.string().nullable(), address: z.string(), is_account_customer: z.boolean(), @@ -800,7 +800,7 @@ const PatchedContactMethodRequest = z .partial() const CompanyCreateRequest = z.object({ name: z.string().min(1).max(255), - email: z.string().email().nullish(), + email: z.union([z.string(), z.string()]).nullish(), phone: z.string().nullish(), address: z.string().nullish(), is_account_customer: z.boolean().optional().default(true), @@ -914,9 +914,9 @@ const CompanyDefaults = z.object({ starting_job_number: z.number().int().gte(-2147483648).lte(2147483647).optional(), starting_po_number: z.number().int().gte(-2147483648).lte(2147483647).optional(), po_prefix: z.string().max(10).optional(), - master_quote_template_url: z.string().max(200).url().nullish(), + master_quote_template_url: z.union([z.string(), z.string()]).nullish(), master_quote_template_id: z.string().max(100).nullish(), - gdrive_quotes_folder_url: z.string().max(200).url().nullish(), + gdrive_quotes_folder_url: z.union([z.string(), z.string()]).nullish(), gdrive_quotes_folder_id: z.string().max(100).nullish(), google_shared_drive_id: z.string().max(100).nullish(), gdrive_how_we_work_folder_id: z.string().max(100).nullish(), @@ -953,8 +953,8 @@ const CompanyDefaults = z.object({ city: z.string().max(100).nullish(), post_code: z.string().max(20).nullish(), country: z.string().max(100).optional(), - company_email: z.string().max(254).email().nullish(), - company_url: z.string().max(200).url().nullish(), + company_email: z.union([z.string(), z.string()]).nullish(), + company_url: z.union([z.string(), z.string()]).nullish(), test_company_name: z.string().max(255).nullish(), kpi_daily_billable_hours_green: z.number().gt(-1000).lt(1000).optional(), kpi_daily_billable_hours_amber: z.number().gt(-1000).lt(1000).optional(), @@ -980,9 +980,9 @@ const CompanyDefaultsRequest = z.object({ starting_job_number: z.number().int().gte(-2147483648).lte(2147483647).optional(), starting_po_number: z.number().int().gte(-2147483648).lte(2147483647).optional(), po_prefix: z.string().min(1).max(10).optional(), - master_quote_template_url: z.string().max(200).url().nullish(), + master_quote_template_url: z.union([z.string(), z.string()]).nullish(), master_quote_template_id: z.string().max(100).nullish(), - gdrive_quotes_folder_url: z.string().max(200).url().nullish(), + gdrive_quotes_folder_url: z.union([z.string(), z.string()]).nullish(), gdrive_quotes_folder_id: z.string().max(100).nullish(), google_shared_drive_id: z.string().max(100).nullish(), gdrive_how_we_work_folder_id: z.string().max(100).nullish(), @@ -1017,8 +1017,8 @@ const CompanyDefaultsRequest = z.object({ city: z.string().max(100).nullish(), post_code: z.string().max(20).nullish(), country: z.string().min(1).max(100).optional(), - company_email: z.string().max(254).email().nullish(), - company_url: z.string().max(200).url().nullish(), + company_email: z.union([z.string(), z.string()]).nullish(), + company_url: z.union([z.string(), z.string()]).nullish(), test_company_name: z.string().max(255).nullish(), kpi_daily_billable_hours_green: z.number().gt(-1000).lt(1000).optional(), kpi_daily_billable_hours_amber: z.number().gt(-1000).lt(1000).optional(), @@ -1045,9 +1045,9 @@ const PatchedCompanyDefaultsRequest = z starting_job_number: z.number().int().gte(-2147483648).lte(2147483647), starting_po_number: z.number().int().gte(-2147483648).lte(2147483647), po_prefix: z.string().min(1).max(10), - master_quote_template_url: z.string().max(200).url().nullable(), + master_quote_template_url: z.union([z.string(), z.string()]).nullable(), master_quote_template_id: z.string().max(100).nullable(), - gdrive_quotes_folder_url: z.string().max(200).url().nullable(), + gdrive_quotes_folder_url: z.union([z.string(), z.string()]).nullable(), gdrive_quotes_folder_id: z.string().max(100).nullable(), google_shared_drive_id: z.string().max(100).nullable(), gdrive_how_we_work_folder_id: z.string().max(100).nullable(), @@ -1082,8 +1082,8 @@ const PatchedCompanyDefaultsRequest = z city: z.string().max(100).nullable(), post_code: z.string().max(20).nullable(), country: z.string().min(1).max(100), - company_email: z.string().max(254).email().nullable(), - company_url: z.string().max(200).url().nullable(), + company_email: z.union([z.string(), z.string()]).nullable(), + company_url: z.union([z.string(), z.string()]).nullable(), test_company_name: z.string().max(255).nullable(), kpi_daily_billable_hours_green: z.number().gt(-1000).lt(1000), kpi_daily_billable_hours_amber: z.number().gt(-1000).lt(1000), @@ -1218,7 +1218,7 @@ const PhoneProviderSettings = z.object({ id: z.number().int(), downloads_enabled: z.boolean().optional(), recording_deletion_enabled: z.boolean().optional(), - base_url: z.string().max(200).url().nullish(), + base_url: z.union([z.string(), z.string()]).nullish(), has_username: z.boolean(), has_password: z.boolean(), account_code: z.string().max(100).optional(), @@ -1229,7 +1229,7 @@ const PatchedPhoneProviderSettingsRequest = z .object({ downloads_enabled: z.boolean(), recording_deletion_enabled: z.boolean(), - base_url: z.string().max(200).url().nullable(), + base_url: z.union([z.string(), z.string()]).nullable(), username: z.string(), password: z.string(), account_code: z.string().max(100), @@ -1545,7 +1545,7 @@ const SpeedQualityTradeoffEnum = z.enum(['fast', 'normal', 'quality']) const QuoteSpreadsheet = z.object({ id: z.string().uuid(), sheet_id: z.string().max(100), - sheet_url: z.string().max(500).url().nullish(), + sheet_url: z.union([z.string(), z.string()]).nullish(), tab: z.string().max(100).nullish(), job_id: z.string(), job_number: z.number().int(), @@ -1559,7 +1559,7 @@ const Quote = z.object({ date: z.string(), total_excl_tax: z.number(), total_incl_tax: z.number(), - online_url: z.string().max(200).url().nullish(), + online_url: z.union([z.string(), z.string()]).nullish(), }) const InvoiceStatusEnum = z.enum(['DRAFT', 'SUBMITTED', 'AUTHORISED', 'DELETED', 'VOIDED', 'PAID']) const Invoice = z.object({ @@ -1573,18 +1573,18 @@ const Invoice = z.object({ total_incl_tax: z.number(), amount_due: z.number(), tax: z.number().optional(), - online_url: z.string().max(200).url().nullish(), + online_url: z.union([z.string(), z.string()]).nullish(), }) const XeroQuote = z .object({ status: QuoteStatusEnum, - online_url: z.string().max(200).url().nullable(), + online_url: z.union([z.string(), z.string()]).nullable(), }) .partial() const XeroInvoice = z.object({ number: z.string().max(255), status: InvoiceStatusEnum.optional(), - online_url: z.string().max(200).url().nullish(), + online_url: z.union([z.string(), z.string()]).nullish(), }) const RdtiTypeEnum = z.enum(['non_rd', 'core_rd', 'supporting_rd']) const BlankEnum = z.unknown() @@ -2035,7 +2035,9 @@ const ApplyQuoteErrorResponse = z.object({ error: z.string(), }) const QuoteSyncErrorResponse = z.object({ error: z.string() }) -const LinkQuoteSheetRequest = z.object({ template_url: z.string().url() }).partial() +const LinkQuoteSheetRequest = z + .object({ template_url: z.union([z.string(), z.string()]) }) + .partial() const LinkQuoteSheetResponse = z.object({ sheet_url: z.string().url(), sheet_id: z.string(), @@ -2510,7 +2512,7 @@ const PersonCompanySummary = z.object({ const PersonSummary = z.object({ id: z.string().uuid(), name: z.string().max(255), - email: z.string().max(254).email().nullish(), + email: z.union([z.string(), z.string()]).nullish(), is_active: z.boolean(), primary_phone: z.string(), companies: z.array(PersonCompanySummary), @@ -2525,7 +2527,7 @@ const PaginatedPersonSummaryList = z.object({ const PersonDetail = z.object({ id: z.string().uuid(), name: z.string().max(255), - email: z.string().max(254).email().nullish(), + email: z.union([z.string(), z.string()]).nullish(), is_active: z.boolean(), created_at: z.string().datetime({ offset: true }), updated_at: z.string().datetime({ offset: true }), @@ -2536,19 +2538,19 @@ const PersonDetail = z.object({ const PersonIdentityUpdateRequest = z .object({ name: z.string().min(1).max(255), - email: z.string().max(254).email().nullable(), + email: z.union([z.string(), z.string()]).nullable(), }) .partial() const PersonIdentityUpdate = z .object({ name: z.string().max(255), - email: z.string().max(254).email().nullable(), + email: z.union([z.string(), z.string()]).nullable(), }) .partial() const PatchedPersonIdentityUpdateRequest = z .object({ name: z.string().min(1).max(255), - email: z.string().max(254).email().nullable(), + email: z.union([z.string(), z.string()]).nullable(), }) .partial() const CompanyLinkWriteRequest = z @@ -2667,7 +2669,7 @@ const ProcedureList = z.object({ document_number: z.string().max(50).nullish(), title: z.string().max(255), site_location: z.string().max(500).optional(), - google_doc_url: z.string().max(200).url().optional(), + google_doc_url: z.union([z.string(), z.string()]).optional(), job_number: z.string().nullable(), tags: z.unknown().optional(), status: ProcedureStatusEnum.optional(), @@ -2947,7 +2949,7 @@ const PurchaseOrderDetail = z.object({ status: PurchaseOrderDetailStatusEnum.optional(), order_date: z.string().optional(), expected_delivery: z.string().nullish(), - online_url: z.string().max(500).url().nullish(), + online_url: z.union([z.string(), z.string()]).nullish(), xero_id: z.string().uuid().nullish(), pickup_address_id: z.string().uuid().nullable(), created_by_id: z.string().uuid().nullable(), @@ -3692,7 +3694,7 @@ const XeroInvoiceCreateRequest = z.object({ const XeroDocumentSuccessResponse = z.object({ success: z.boolean().optional().default(true), xero_id: z.string().uuid(), - online_url: z.string().url().optional(), + online_url: z.union([z.string(), z.string()]).optional(), messages: z.array(z.string()).optional(), company: z.string().optional(), total_excl_tax: z.number().gt(-10000000000).lt(10000000000).optional(), @@ -6512,7 +6514,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/link/`, { name: 'body', type: 'Body', - schema: z.object({ template_url: z.string().url() }).partial(), + schema: LinkQuoteSheetRequest, }, { name: 'id', diff --git a/frontend/src/components/CreateCompanyModal.vue b/frontend/src/components/CreateCompanyModal.vue index 8660db70b..33e78f395 100644 --- a/frontend/src/components/CreateCompanyModal.vue +++ b/frontend/src/components/CreateCompanyModal.vue @@ -427,8 +427,7 @@ const handleDuplicateCompanyError = (error: unknown): boolean => { } const existingCompany = parsedDuplicate.data.existing_company as - | Record - | undefined + Record | undefined const nameValue = typeof existingCompany?.name === 'string' ? existingCompany.name : 'Existing company' const xeroIdValue = diff --git a/frontend/src/components/TaskExecutionsModal.vue b/frontend/src/components/TaskExecutionsModal.vue index 01f2667ce..f9a7993ee 100644 --- a/frontend/src/components/TaskExecutionsModal.vue +++ b/frontend/src/components/TaskExecutionsModal.vue @@ -73,8 +73,7 @@
Traceback
{{ exec.traceback }}
+ >{{ exec.traceback }} diff --git a/frontend/src/components/admin/errors/ErrorDialog.vue b/frontend/src/components/admin/errors/ErrorDialog.vue index 858260557..0ee7df41f 100644 --- a/frontend/src/components/admin/errors/ErrorDialog.vue +++ b/frontend/src/components/admin/errors/ErrorDialog.vue @@ -131,8 +131,7 @@ const errorTypeLabel = computed(() => {
{{ rawPayload }}
+ >{{ rawPayload }}
' }, +} + +const existingProvider = { + id: 7, + name: 'Gemini prod', + provider_type: 'Gemini' as const, + model_name: 'gemini-flash-latest', + default: true, +} + +// vee-validate resolves the validation schema across macrotasks, so a +// microtask flush alone lands before the submit handler runs. Poll for the +// emit rather than guessing a delay. +async function submitAndGetSaved(wrapper: ReturnType) { + await wrapper.find('form').trigger('submit') + await vi.waitUntil(() => wrapper.emitted('save')) + await flushPromises() + return wrapper.emitted('save')?.at(-1)?.[0] as Record +} + +describe('AIProviderFormModal model_name', () => { + it('emits null when an existing model name is cleared, so it can be unset', async () => { + const wrapper = mount(AIProviderFormModal, { + props: { provider: existingProvider }, + global: { stubs }, + }) + + await wrapper.find('#model_name').setValue('') + + // Omitting the key would leave the stored name in place: PATCH only + // writes fields it is sent. + expect(await submitAndGetSaved(wrapper)).toHaveProperty('model_name', null) + }) + + it('emits null rather than "" when creating a provider with no model name', async () => { + const wrapper = mount(AIProviderFormModal, { + props: { provider: null }, + global: { stubs }, + }) + + await wrapper.find('#name').setValue('New provider') + await wrapper.find('#api_key').setValue('sk-test') + + // The column's unset is NULL and the serializer rejects "" outright. + expect(await submitAndGetSaved(wrapper)).toHaveProperty('model_name', null) + }) + + it('emits the entered model name unchanged', async () => { + const wrapper = mount(AIProviderFormModal, { + props: { provider: existingProvider }, + global: { stubs }, + }) + + await wrapper.find('#model_name').setValue('gemini-pro-latest') + + expect(await submitAndGetSaved(wrapper)).toHaveProperty('model_name', 'gemini-pro-latest') + }) +}) From 33e248936dd96e5abbc062ee9f360a791b38b6fd Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 12:58:42 +1200 Subject: [PATCH 09/39] fix: reconcile kanban changes incrementally --- apps/job/__init__.py | 5 + apps/job/etag.py | 20 + apps/job/kanban_version.py | 57 +++ apps/job/serializers/__init__.py | 2 + apps/job/serializers/job_serializer.py | 5 +- apps/job/serializers/kanban_serializer.py | 15 +- apps/job/services/__init__.py | 7 +- apps/job/services/job_rest_service.py | 100 ++-- apps/job/services/kanban_service.py | 51 ++ apps/job/tests/test_event_deduplication.py | 31 +- apps/job/tests/test_job_rest_error_mapping.py | 33 +- apps/job/tests/test_job_rest_service.py | 8 +- apps/job/tests/test_kanban_changes.py | 208 ++++++++ apps/job/urls.py | 5 + apps/job/views/__init__.py | 2 + apps/job/views/job_rest_views.py | 137 ++---- apps/job/views/kanban_view_api.py | 60 +++ apps/purchasing/__init__.py | 5 +- apps/purchasing/etag.py | 27 +- apps/purchasing/serializers.py | 7 + .../services/delivery_receipt_service.py | 36 +- .../services/purchasing_rest_service.py | 11 +- .../tests/test_purchase_order_etags.py | 100 ++++ .../purchasing/views/purchasing_rest_views.py | 89 ++-- apps/workflow/__init__.py | 14 + apps/workflow/etag.py | 50 ++ apps/workflow/serializers.py | 13 + .../workflow/tests/test_data_versions_view.py | 21 +- apps/workflow/tests/test_etag.py | 37 ++ apps/workflow/views/data_versions_view.py | 22 +- docs/urls/job.md | 1 + frontend/schema.yml | 381 +++++++++++---- frontend/src/api/generated/api.ts | 166 ++++--- .../__tests__/useDataFreshness.test.ts | 51 ++ .../__tests__/useOptimizedKanban.test.ts | 454 ++++++++++++++++++ frontend/src/composables/useDataFreshness.ts | 19 +- .../src/composables/useOptimizedKanban.ts | 329 ++++++++++--- frontend/src/services/job.service.ts | 5 + frontend/src/stores/__tests__/jobs.test.ts | 28 +- frontend/src/stores/jobs.ts | 2 +- frontend/src/typed-router.d.ts | 84 +++- 41 files changed, 2197 insertions(+), 501 deletions(-) create mode 100644 apps/job/etag.py create mode 100644 apps/job/kanban_version.py create mode 100644 apps/job/tests/test_kanban_changes.py create mode 100644 apps/purchasing/tests/test_purchase_order_etags.py create mode 100644 apps/workflow/etag.py create mode 100644 apps/workflow/tests/test_etag.py create mode 100644 frontend/src/composables/__tests__/useDataFreshness.test.ts diff --git a/apps/job/__init__.py b/apps/job/__init__.py index fdb6157a7..54adbbb90 100644 --- a/apps/job/__init__.py +++ b/apps/job/__init__.py @@ -10,6 +10,8 @@ if apps.ready: from .diff import DiffResult, apply_diff, diff_costset + from .etag import current_job_etag_value, generate_job_etag + from .kanban_version import KanbanDatasetVersion from .mixins import JobLookupMixin, JobNumberLookupMixin from .permissions import IsOfficeStaff, IsStaffUser from .tasks import ( @@ -30,13 +32,16 @@ "JobConfig", "JobLookupMixin", "JobNumberLookupMixin", + "KanbanDatasetVersion", "MetalType", "RDTIType", "SpeedQualityTradeoff", "apply_diff", "auto_archive_completed_jobs_task", "create_job_file_thumbnail_task", + "current_job_etag_value", "diff_costset", + "generate_job_etag", "get_active_jobs", "get_job_folder_path", "request_job_summary_pdf_refresh", diff --git a/apps/job/etag.py b/apps/job/etag.py new file mode 100644 index 000000000..ba5d04831 --- /dev/null +++ b/apps/job/etag.py @@ -0,0 +1,20 @@ +"""ETag utilities for the Job aggregate.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from apps.workflow.etag import generate_updated_at_etag, updated_at_etag_value + +if TYPE_CHECKING: + from apps.job.models import Job + + +def current_job_etag_value(job: Job) -> str: + """Return the full-precision validator value for a Job.""" + return updated_at_etag_value("job", job.id, job.updated_at) + + +def generate_job_etag(job: Job) -> str: + """Return the strong HTTP ETag for a Job.""" + return generate_updated_at_etag("job", job.id, job.updated_at) diff --git a/apps/job/kanban_version.py b/apps/job/kanban_version.py new file mode 100644 index 000000000..896cfc6c9 --- /dev/null +++ b/apps/job/kanban_version.py @@ -0,0 +1,57 @@ +"""Opaque version contract for incremental Kanban reconciliation.""" + +from dataclasses import dataclass +from datetime import UTC, datetime + +from django.utils import timezone + +_EMPTY_TIMESTAMP = datetime(1970, 1, 1, tzinfo=UTC) + + +@dataclass(frozen=True) +class KanbanDatasetVersion: + """Typed representation of the Job dataset version sent to clients.""" + + updated_at: datetime + created_at: datetime + count: int + + @classmethod + def from_values( + cls, + *, + updated_at: datetime | None, + created_at: datetime | None, + count: int, + ) -> "KanbanDatasetVersion": + if count < 0: + raise ValueError("Kanban version count cannot be negative") + if updated_at is not None and timezone.is_naive(updated_at): + raise ValueError("Kanban updated_at version must be timezone-aware") + if created_at is not None and timezone.is_naive(created_at): + raise ValueError("Kanban created_at version must be timezone-aware") + + return cls( + updated_at=(updated_at or _EMPTY_TIMESTAMP).astimezone(UTC), + created_at=(created_at or _EMPTY_TIMESTAMP).astimezone(UTC), + count=count, + ) + + def encode(self) -> str: + """Encode the version for transport as an opaque string.""" + updated = self.updated_at.isoformat(timespec="microseconds") + created = self.created_at.isoformat(timespec="microseconds") + return f"{updated}|{created}|{self.count}" + + @classmethod + def decode(cls, value: str) -> "KanbanDatasetVersion": + """Decode and validate a previously emitted version.""" + try: + updated_value, created_value, count_value = value.split("|") + return cls.from_values( + updated_at=datetime.fromisoformat(updated_value), + created_at=datetime.fromisoformat(created_value), + count=int(count_value), + ) + except (TypeError, ValueError) as exc: + raise ValueError("Invalid Kanban version") from exc diff --git a/apps/job/serializers/__init__.py b/apps/job/serializers/__init__.py index 701c22210..61be51055 100644 --- a/apps/job/serializers/__init__.py +++ b/apps/job/serializers/__init__.py @@ -146,6 +146,7 @@ JobReorderSerializer, JobSearchFiltersSerializer, JobStatusUpdateSerializer, + KanbanChangesResponseSerializer, KanbanColumnJobSerializer, KanbanErrorResponseSerializer, KanbanJobPersonSerializer, @@ -284,6 +285,7 @@ "JobSummarySerializer", "JobTimelineResponseSerializer", "JobUndoSerializer", + "KanbanChangesResponseSerializer", "KanbanColumnJobSerializer", "KanbanErrorResponseSerializer", "KanbanJobPersonSerializer", diff --git a/apps/job/serializers/job_serializer.py b/apps/job/serializers/job_serializer.py index c50a8f724..c02630678 100644 --- a/apps/job/serializers/job_serializer.py +++ b/apps/job/serializers/job_serializer.py @@ -11,6 +11,7 @@ from apps.company.models import Company, Person from apps.job.models import Job, JobEvent, JobFile from apps.workflow.models import XeroPayItem +from apps.workflow.serializers import AppErrorResponseSerializer from .costing_serializer import ( CostSetSerializer, @@ -531,11 +532,9 @@ class JobDetailResponseSerializer(serializers.Serializer): data = JobDataSerializer() -class JobRestErrorResponseSerializer(serializers.Serializer): +class JobRestErrorResponseSerializer(AppErrorResponseSerializer): """Serializer for job REST error responses.""" - error = serializers.CharField() - class JobDeleteResponseSerializer(serializers.Serializer): """Serializer for job deletion response.""" diff --git a/apps/job/serializers/kanban_serializer.py b/apps/job/serializers/kanban_serializer.py index 92e114fcb..515858a32 100644 --- a/apps/job/serializers/kanban_serializer.py +++ b/apps/job/serializers/kanban_serializer.py @@ -4,6 +4,8 @@ from rest_framework import serializers +from apps.workflow.serializers import AppErrorResponseSerializer + class JobReorderSerializer(serializers.Serializer): """Serializer for job reorder request data.""" @@ -56,11 +58,10 @@ class KanbanSuccessResponseSerializer(serializers.Serializer): message = serializers.CharField() -class KanbanErrorResponseSerializer(serializers.Serializer): +class KanbanErrorResponseSerializer(AppErrorResponseSerializer): """Serializer for error kanban operation response.""" success = serializers.BooleanField(default=False) - error = serializers.CharField() class JobSearchFiltersSerializer(serializers.Serializer): @@ -263,6 +264,16 @@ class FetchJobsByColumnResponseSerializer(serializers.Serializer): error = serializers.CharField(required=False) +class KanbanChangesResponseSerializer(serializers.Serializer): + """Serializer for incremental Kanban freshness reconciliation.""" + + success = serializers.BooleanField(default=True) + jobs = KanbanColumnJobSerializer(many=True) + removed_job_ids = serializers.ListField(child=serializers.UUIDField()) + full_refresh_required = serializers.BooleanField() + error = serializers.CharField(required=False) + + class WorkshopJobSerializer(serializers.Serializer): id = serializers.UUIDField() name = serializers.CharField() diff --git a/apps/job/services/__init__.py b/apps/job/services/__init__.py index fc06cea8e..07b7c19aa 100644 --- a/apps/job/services/__init__.py +++ b/apps/job/services/__init__.py @@ -50,7 +50,11 @@ KanbanCategorizationService, KanbanColumn, ) - from .kanban_service import KanbanSerializationContext, KanbanService + from .kanban_service import ( + KanbanChanges, + KanbanSerializationContext, + KanbanService, + ) from .labour_subtype_service import seed_subtype_onto_existing_jobs from .mcp_chat_service import MCPChatService from .month_end_service import MonthEndService @@ -116,6 +120,7 @@ "JobStaffService", "JobSummaryPdfService", "KanbanCategorizationService", + "KanbanChanges", "KanbanColumn", "KanbanSerializationContext", "KanbanService", diff --git a/apps/job/services/job_rest_service.py b/apps/job/services/job_rest_service.py index 3e4a74ab0..fd7828f27 100644 --- a/apps/job/services/job_rest_service.py +++ b/apps/job/services/job_rest_service.py @@ -22,6 +22,7 @@ from apps.accounts.models import Staff from apps.company.models import Company, Person +from apps.job.etag import current_job_etag_value, generate_job_etag from apps.job.models import Job, JobDeltaRejection, JobEvent, LabourSubtype from apps.job.models.costing import CostLine from apps.job.serializers import JobSerializer @@ -33,6 +34,7 @@ QuoteSerializer, ) from apps.job.services.delta_checksum import compute_job_delta_checksum, normalise_value +from apps.workflow.etag import if_match_satisfied from apps.workflow.models import CompanyDefaults, XeroPayItem from apps.workflow.services.error_persistence import persist_app_error @@ -58,18 +60,6 @@ def __init__( self.server_checksum = server_checksum -def _current_job_etag_value(job: Job) -> str: - """ - Return normalized ETag value for comparison (without W/ and quotes). - Mirrors BaseJobRestView._gen_job_etag but normalized. - """ - try: - ts_ms = int(job.updated_at.timestamp() * 1000) - except Exception: - ts_ms = 0 - return f"job:{job.id}:{ts_ms}" - - @dataclass class JobDeltaPayload: """ @@ -990,7 +980,7 @@ def mark_job_delta_rejection_group_unresolved_by_fingerprint( @staticmethod def update_job( - job_id: UUID, data: Dict[str, Any], user: Staff, if_match: str | None = None + job_id: UUID, data: Dict[str, Any], user: Staff, if_match: str ) -> Job: """ Updates an existing Job with optimistic concurrency control (ETag). @@ -1060,20 +1050,15 @@ def update_job( # Concurrency check using normalized ETag value - AFTER delta validation logger.debug("[JOB_UPDATE] Checking ETag precondition...") - if not if_match: - logger.warning( - "[JOB_UPDATE] No If-Match header provided - skipping ETag validation" + current_etag = generate_job_etag(job) + logger.debug(f"[JOB_UPDATE] Current ETag: {current_etag}") + logger.debug(f"[JOB_UPDATE] Company ETag: {if_match}") + if not if_match_satisfied(if_match, current_etag): + logger.error( + f"[JOB_UPDATE] ETag mismatch! Current: {current_etag}, Expected: {if_match}" ) - else: - current_norm = _current_job_etag_value(job) - logger.debug(f"[JOB_UPDATE] Current ETag: {current_norm}") - logger.debug(f"[JOB_UPDATE] Company ETag: {if_match}") - if current_norm != if_match: - logger.error( - f"[JOB_UPDATE] ETag mismatch! Current: {current_norm}, Expected: {if_match}" - ) - raise PreconditionFailed("ETag mismatch: resource has changed") - logger.debug("[JOB_UPDATE] ETag validation passed") + raise PreconditionFailed("ETag mismatch: resource has changed") + logger.debug("[JOB_UPDATE] ETag validation passed") # DEBUG: Log incoming data logger.debug(f"JobRestService.update_job - Incoming data: {data}") @@ -1194,7 +1179,7 @@ def undo_job_change( job_id: UUID, change_id: UUID, user: Staff, - if_match: str | None = None, + if_match: str, undo_change_id: UUID | None = None, ) -> Job: """Undo a previously recorded delta by reverting to its before state.""" @@ -1258,7 +1243,7 @@ def undo_job_change( "before_checksum": checksum, "actor_id": str(user.id), "made_at": timezone.now().isoformat(), - "etag": _current_job_etag_value(job), + "etag": current_job_etag_value(job), "undo_of_change_id": str(change_id), } @@ -1305,7 +1290,9 @@ def toggle_complex_job( @staticmethod @transaction.atomic - def add_job_event(job_id: UUID, description: str, user: Staff) -> Dict[str, Any]: + def add_job_event( + job_id: UUID, description: str, user: Staff, if_match: str + ) -> Dict[str, Any]: """ Adds a manual event to the Job with duplicate prevention. @@ -1324,6 +1311,9 @@ def add_job_event(job_id: UUID, description: str, user: Staff) -> Dict[str, Any] # Lock the job to prevent race conditions job = Job.objects.select_for_update().get(id=job_id) + current_etag = generate_job_etag(job) + if not if_match_satisfied(if_match, current_etag): + raise PreconditionFailed("ETag mismatch: resource has changed") description_clean = description.strip() @@ -1363,6 +1353,8 @@ def add_job_event(job_id: UUID, description: str, user: Staff) -> Dict[str, Any] f"Event already exists for job {job_id} by user {user.email}. " f"Returning existing event: {event.id}" ) + else: + Job.objects.filter(pk=job.pk).update(updated_at=timezone.now()) logger.info( f"Event {event.id} {'created' if created else 'found'} " @@ -1384,11 +1376,13 @@ def add_job_event(job_id: UUID, description: str, user: Staff) -> Dict[str, Any] } except Job.DoesNotExist as exc: + persist_app_error(exc, job_id=str(job_id), user_id=str(user.id)) error_msg = f"Job {job_id} not found" logger.error(error_msg) raise ValueError(error_msg) from exc except (ValidationError, IntegrityError) as e: + persist_app_error(e, job_id=str(job_id), user_id=str(user.id)) # Handle duplicate constraint violations logger.warning( f"Duplicate event constraint violation for job {job_id} by user {user.email}: {e}" @@ -1417,34 +1411,27 @@ def add_job_event(job_id: UUID, description: str, user: Staff) -> Dict[str, Any] raise @staticmethod - def delete_job( - job_id: UUID, user: Staff, if_match: str | None = None - ) -> Dict[str, Any]: + def delete_job(job_id: UUID, user: Staff, if_match: str) -> Dict[str, Any]: """ Deletes a Job if allowed by business rules and ETag precondition matches. """ - # Lock row during deletion checks - job = get_object_or_404(Job.objects.select_for_update(), id=job_id) - - # Concurrency check - if if_match: - current_norm = _current_job_etag_value(job) - if current_norm != if_match: + with transaction.atomic(): + job = get_object_or_404(Job.objects.select_for_update(), id=job_id) + current_etag = generate_job_etag(job) + if not if_match_satisfied(if_match, current_etag): raise PreconditionFailed("ETag mismatch: resource has changed") - actual_cost_set = job.latest_actual - - if actual_cost_set and ( - actual_cost_set.summary.get("cost", 0) > 0 - or actual_cost_set.summary.get("rev", 0) > 0 - ): - raise ValueError( - "Cannot delete this job because it has real costs or revenue." - ) + actual_cost_set = job.latest_actual + if actual_cost_set and ( + actual_cost_set.summary.get("cost", 0) > 0 + or actual_cost_set.summary.get("rev", 0) > 0 + ): + raise ValueError( + "Cannot delete this job because it has real costs or revenue." + ) - job_name = job.name - job_number = job.job_number - with transaction.atomic(): + job_name = job.name + job_number = job.job_number job.delete() logger.info(f"Job {job_number} '{job_name}' deleted by {user.email}") @@ -1452,9 +1439,7 @@ def delete_job( return {"success": True, "message": f"Job {job_number} deleted successfully"} @staticmethod - def accept_quote( - job_id: UUID, user: Staff, if_match: str | None = None - ) -> Dict[str, Any]: + def accept_quote(job_id: UUID, user: Staff, if_match: str) -> Dict[str, Any]: """ Accept a quote for a job by setting the quote_acceptance_date and changing status to approved. Enforces optimistic concurrency via If-Match (ETag) precondition. @@ -1462,10 +1447,9 @@ def accept_quote( with transaction.atomic(): job = get_object_or_404(Job.objects.select_for_update(), id=job_id) - if if_match: - current_norm = _current_job_etag_value(job) - if current_norm != if_match: - raise PreconditionFailed("ETag mismatch: resource has changed") + current_etag = generate_job_etag(job) + if not if_match_satisfied(if_match, current_etag): + raise PreconditionFailed("ETag mismatch: resource has changed") if not job.latest_quote: raise ValueError("No quote found for this job") diff --git a/apps/job/services/kanban_service.py b/apps/job/services/kanban_service.py index 1cd1c1d23..86060b76c 100644 --- a/apps/job/services/kanban_service.py +++ b/apps/job/services/kanban_service.py @@ -17,6 +17,7 @@ from django.db import transaction from django.db.models import ( Case, + Count, Exists, ExpressionWrapper, F, @@ -35,6 +36,7 @@ from apps.accounting.models import Invoice from apps.accounts.models import Staff from apps.company.models import Company, Person +from apps.job.kanban_version import KanbanDatasetVersion from apps.job.models import CostSet, Job from apps.job.services.kanban_categorization_service import KanbanCategorizationService from apps.workflow.models import CompanyDefaults @@ -62,6 +64,15 @@ class KanbanSerializationContext: people_by_job: Dict[UUID, List[Staff]] +@dataclass(frozen=True) +class KanbanChanges: + """Typed domain result for incremental Kanban reconciliation.""" + + jobs: list[Job] + removed_job_ids: list[UUID] + full_refresh_required: bool + + class KanbanService: """Service class for Kanban business logic.""" @@ -79,6 +90,46 @@ class KanbanService: SEARCH_SCORE_MIN_DISPLAY = 15.0 SEARCH_SCORE_ORDER_NUMBER_MATCH = 75.0 + @staticmethod + def get_kanban_changes(after: str) -> KanbanChanges: + """Return changed cards since an opaque Job dataset version.""" + previous = KanbanDatasetVersion.decode(after) + + current = Job.objects.aggregate( + count=Count("id"), + latest_created=Max("created_at"), + ) + current_topology = KanbanDatasetVersion.from_values( + updated_at=None, + created_at=current["latest_created"], + count=current["count"], + ) + if ( + current_topology.count != previous.count + or current_topology.created_at != previous.created_at + ): + return KanbanChanges( + jobs=[], + removed_job_ids=[], + full_refresh_required=True, + ) + + changed_jobs = Job.objects.filter(updated_at__gt=previous.updated_at) + visible_jobs = KanbanService.filter_kanban_jobs(changed_jobs) + visible_ids = set(visible_jobs.values_list("id", flat=True)) + removed_job_ids = [ + job_id + for job_id in changed_jobs.exclude(id__in=visible_ids).values_list( + "id", flat=True + ) + ] + + return KanbanChanges( + jobs=list(visible_jobs), + removed_job_ids=removed_job_ids, + full_refresh_required=False, + ) + TEXT_SEARCH_FIELDS: List[Dict[str, Any]] = [ { "db_path": "name", diff --git a/apps/job/tests/test_event_deduplication.py b/apps/job/tests/test_event_deduplication.py index 52177ea0d..80231d499 100644 --- a/apps/job/tests/test_event_deduplication.py +++ b/apps/job/tests/test_event_deduplication.py @@ -4,6 +4,7 @@ from apps.accounts.models import Staff from apps.company.models import Company +from apps.job.etag import generate_job_etag from apps.job.models import Job, JobEvent from apps.job.services.job_rest_service import JobRestService from apps.testing import BaseTestCase @@ -94,11 +95,22 @@ def test_service_prevents_duplicate_events(self): """ description = "Test service event" - result1 = JobRestService.add_job_event(self.job.id, description, self.user) + result1 = JobRestService.add_job_event( + self.job.id, + description, + self.user, + generate_job_etag(self.job), + ) self.assertTrue(result1["success"]) self.assertFalse(result1.get("duplicate_prevented", False)) - result2 = JobRestService.add_job_event(self.job.id, description, self.user) + self.job.refresh_from_db() + result2 = JobRestService.add_job_event( + self.job.id, + description, + self.user, + generate_job_etag(self.job), + ) self.assertTrue(result2["success"]) self.assertTrue(result2.get("duplicate_prevented", False)) @@ -126,10 +138,21 @@ def test_different_users_can_create_same_event(self): description = "Same description" - result1 = JobRestService.add_job_event(self.job.id, description, self.user) + result1 = JobRestService.add_job_event( + self.job.id, + description, + self.user, + generate_job_etag(self.job), + ) self.assertTrue(result1["success"]) - result2 = JobRestService.add_job_event(self.job.id, description, user2) + self.job.refresh_from_db() + result2 = JobRestService.add_job_event( + self.job.id, + description, + user2, + generate_job_etag(self.job), + ) self.assertTrue(result2["success"]) self.assertFalse(result2.get("duplicate_prevented", False)) diff --git a/apps/job/tests/test_job_rest_error_mapping.py b/apps/job/tests/test_job_rest_error_mapping.py index f31740b54..0a1f81fdf 100644 --- a/apps/job/tests/test_job_rest_error_mapping.py +++ b/apps/job/tests/test_job_rest_error_mapping.py @@ -10,6 +10,8 @@ through the generated client, where `error` is a required key. """ +from uuid import UUID + from django.db import IntegrityError from django.http import Http404 from rest_framework import status @@ -29,17 +31,18 @@ def setUp(self) -> None: self.view = BaseJobRestView() def assert_maps_to( - self, error: Exception, expected_status: int, expected_body: dict[str, str] + self, error: Exception, expected_status: int, expected_error: str ) -> None: response = self.view.handle_service_error(error) self.assertEqual(response.status_code, expected_status) - self.assertEqual(response.data, expected_body) + self.assertEqual(response.data["error"], expected_error) + UUID(str(response.data["details"]["error_id"])) def test_value_error_is_a_bad_request(self) -> None: self.assert_maps_to( ValueError("Job with id abc not found"), status.HTTP_400_BAD_REQUEST, - {"error": "Job with id abc not found"}, + "Job with id abc not found", ) def test_value_error_subclasses_are_bad_requests_not_server_errors(self) -> None: @@ -52,18 +55,14 @@ def test_value_error_subclasses_are_bad_requests_not_server_errors(self) -> None self.assert_maps_to( error, status.HTTP_400_BAD_REQUEST, - {"error": str(error)}, + str(error), ) def test_precondition_failed_is_412(self) -> None: self.assert_maps_to( PreconditionFailed("etag mismatch"), status.HTTP_412_PRECONDITION_FAILED, - { - "error": ( - "Precondition failed (ETag mismatch). Reload the job and retry." - ) - }, + "Precondition failed (ETag mismatch). Reload the job and retry.", ) def test_delta_validation_error_is_412_not_shadowed(self) -> None: @@ -72,11 +71,7 @@ def test_delta_validation_error_is_412_not_shadowed(self) -> None: self.assert_maps_to( DeltaValidationError("checksum mismatch"), status.HTTP_412_PRECONDITION_FAILED, - { - "error": ( - "Precondition failed (ETag mismatch). Reload the job and retry." - ) - }, + "Precondition failed (ETag mismatch). Reload the job and retry.", ) def test_not_found_variants_are_404(self) -> None: @@ -85,28 +80,28 @@ def test_not_found_variants_are_404(self) -> None: self.assert_maps_to( error, status.HTTP_404_NOT_FOUND, - {"error": "Resource not found"}, + "gone", ) def test_integrity_error_is_409(self) -> None: self.assert_maps_to( IntegrityError("duplicate key"), status.HTTP_409_CONFLICT, - {"error": "Duplicate event prevented by database constraint"}, + "duplicate key", ) def test_permission_error_is_403(self) -> None: self.assert_maps_to( PermissionError("not allowed"), status.HTTP_403_FORBIDDEN, - {"error": "not allowed"}, + "not allowed", ) - def test_unmapped_exception_is_500_without_leaking_the_message(self) -> None: + def test_unmapped_exception_is_500_with_persisted_message_and_id(self) -> None: self.assert_maps_to( RuntimeError("internal detail that should not ship"), status.HTTP_500_INTERNAL_SERVER_ERROR, - {"error": "Internal server error"}, + "internal detail that should not ship", ) diff --git a/apps/job/tests/test_job_rest_service.py b/apps/job/tests/test_job_rest_service.py index 8175cb221..a343d1b1f 100644 --- a/apps/job/tests/test_job_rest_service.py +++ b/apps/job/tests/test_job_rest_service.py @@ -4,6 +4,7 @@ from django.utils import timezone from apps.company.models import Company, Person +from apps.job.etag import generate_job_etag from apps.job.models import Job, JobDeltaRejection, JobEvent from apps.job.models.costing import CostLine from apps.job.services.job_rest_service import DeltaValidationError, JobRestService @@ -106,7 +107,12 @@ def test_hard_checksum_mismatch_records_the_rejection(self) -> None: } with self.assertRaises(DeltaValidationError): - JobRestService.update_job(job.id, payload, self.test_staff) + JobRestService.update_job( + job.id, + payload, + self.test_staff, + generate_job_etag(job), + ) rejection = JobDeltaRejection.objects.get() self.assertIn("checksum mismatch", rejection.reason.lower()) diff --git a/apps/job/tests/test_kanban_changes.py b/apps/job/tests/test_kanban_changes.py new file mode 100644 index 000000000..14798b709 --- /dev/null +++ b/apps/job/tests/test_kanban_changes.py @@ -0,0 +1,208 @@ +"""Incremental Kanban freshness must update only the affected board structure.""" + +from datetime import timedelta + +from django.utils import timezone + +from apps.accounts.models import Staff +from apps.company.models import Company +from apps.job.etag import generate_job_etag +from apps.job.models import Job +from apps.testing import BaseAPITestCase +from apps.workflow.models import AppError, XeroPayItem + + +class KanbanChangesAPITests(BaseAPITestCase): + def setUp(self) -> None: + super().setUp() + self.client.force_authenticate(self.test_staff) + self.company = Company.objects.create( + name="Kanban Changes Company", + xero_last_modified=timezone.now(), + ) + self.pay_item = XeroPayItem.get_ordinary_time() + self.first_job = self._create_job("First changed-card job", 9101) + self.second_job = self._create_job("Second changed-card job", 9102) + + def _create_job(self, name: str, job_number: int, **overrides: object) -> Job: + values = { + "name": name, + "job_number": job_number, + "company": self.company, + "status": "in_progress", + "created_by": self.test_staff, + "default_xero_pay_item": self.pay_item, + "staff": self.test_staff, + } + values.update(overrides) + return Job.objects.create(**values) + + def _kanban_version(self) -> str: + response = self.client.get("/api/data-versions/") + self.assertEqual(response.status_code, 200) + return response.json()["kanban"] + + def _changes_after(self, version: str): + return self.client.get( + "/api/job/jobs/kanban-changes/", + {"after": version}, + ) + + def test_returns_only_the_changed_card_when_membership_is_unchanged(self) -> None: + version = self._kanban_version() + self.first_job.name = "Renamed first job" + self.first_job.save(staff=self.test_staff, update_fields=["name"]) + + response = self._changes_after(version) + + self.assertEqual(response.status_code, 200) + payload = response.json() + self.assertFalse(payload["full_refresh_required"]) + self.assertEqual( + [job["id"] for job in payload["jobs"]], + [str(self.first_job.id)], + ) + self.assertEqual(payload["jobs"][0]["name"], "Renamed first job") + self.assertEqual(payload["removed_job_ids"], []) + + def test_reports_a_card_removed_when_it_moves_to_hidden_status(self) -> None: + version = self._kanban_version() + self.first_job.status = "special" + self.first_job.save(staff=self.test_staff, update_fields=["status"]) + + response = self._changes_after(version) + + self.assertEqual(response.status_code, 200) + payload = response.json() + self.assertFalse(payload["full_refresh_required"]) + self.assertEqual(payload["jobs"], []) + self.assertEqual(payload["removed_job_ids"], [str(self.first_job.id)]) + + def test_requires_full_refresh_when_job_count_changes(self) -> None: + version = self._kanban_version() + self._create_job("Newly created job", 9103) + + response = self._changes_after(version) + + self.assertEqual(response.status_code, 200) + payload = response.json() + self.assertTrue(payload["full_refresh_required"]) + self.assertEqual(payload["jobs"], []) + self.assertEqual(payload["removed_job_ids"], []) + + def test_requires_full_refresh_for_count_neutral_delete_and_create(self) -> None: + version = self._kanban_version() + self.first_job.delete() + replacement = self._create_job("Replacement job", 9103) + + response = self._changes_after(version) + + self.assertEqual(Job.objects.count(), 2) + self.assertTrue(response.json()["full_refresh_required"]) + self.assertTrue(Job.objects.filter(pk=replacement.pk).exists()) + + def test_rejects_missing_or_malformed_version(self) -> None: + missing = self.client.get("/api/job/jobs/kanban-changes/") + malformed = self._changes_after("not-a-version") + + self.assertEqual(missing.status_code, 400) + self.assertEqual(malformed.status_code, 400) + self.assertIn("error_id", malformed.json()["details"]) + self.assertEqual(AppError.objects.count(), 1) + + +class ManualJobEventETagTests(BaseAPITestCase): + def setUp(self) -> None: + super().setUp() + self.office_staff = Staff.objects.create_user( + email="etag-office@example.test", + password="testpass", + first_name="ETag", + last_name="Office", + is_office_staff=True, + ) + self.client.force_authenticate(self.office_staff) + company = Company.objects.create( + name="ETag Event Company", + xero_last_modified=timezone.now(), + ) + self.job = Job.objects.create( + name="ETag Event Job", + job_number=9201, + company=company, + status="in_progress", + created_by=self.office_staff, + default_xero_pay_item=XeroPayItem.get_ordinary_time(), + staff=self.office_staff, + ) + self.detail_url = f"/api/job/jobs/{self.job.id}/" + self.event_url = f"/api/job/jobs/{self.job.id}/events/create/" + + def _current_etag(self) -> str: + response = self.client.get(self.detail_url) + self.assertEqual(response.status_code, 200) + return response["ETag"] + + def test_event_requires_if_match(self) -> None: + response = self.client.post( + self.event_url, + {"description": "No precondition"}, + format="json", + ) + + self.assertEqual(response.status_code, 428) + self.assertEqual(self.job.events.filter(event_type="manual_note").count(), 0) + + def test_event_rejects_stale_etag_without_creating_an_event(self) -> None: + stale_etag = self._current_etag() + self.job.name = "Concurrent rename" + self.job.save(staff=self.office_staff, update_fields=["name"]) + + response = self.client.post( + self.event_url, + {"description": "Stale note"}, + format="json", + HTTP_IF_MATCH=stale_etag, + ) + + self.assertEqual(response.status_code, 412) + self.assertEqual(self.job.events.filter(event_type="manual_note").count(), 0) + + def test_event_bumps_job_etag_and_updated_at(self) -> None: + original_updated_at = self.job.updated_at + original_etag = self._current_etag() + + response = self.client.post( + self.event_url, + {"description": "Fresh note"}, + format="json", + HTTP_IF_MATCH=original_etag, + ) + + self.assertEqual(response.status_code, 201) + self.job.refresh_from_db() + self.assertGreater(self.job.updated_at, original_updated_at) + self.assertNotEqual(response["ETag"], original_etag) + self.assertFalse(response["ETag"].startswith("W/")) + + def test_event_rejects_a_weak_if_match_tag(self) -> None: + current_etag = self._current_etag() + + response = self.client.post( + self.event_url, + {"description": "Weak precondition"}, + format="json", + HTTP_IF_MATCH=f"W/{current_etag}", + ) + + self.assertEqual(response.status_code, 412) + self.assertIn("error_id", response.json()["details"]) + + def test_job_etag_distinguishes_changes_within_one_millisecond(self) -> None: + first_timestamp = self.job.updated_at + self.job.updated_at = first_timestamp + timedelta(microseconds=100) + + later_etag = generate_job_etag(self.job) + self.job.updated_at = first_timestamp + + self.assertNotEqual(generate_job_etag(self.job), later_etag) diff --git a/apps/job/urls.py b/apps/job/urls.py index 346a7dd85..06bcf0133 100644 --- a/apps/job/urls.py +++ b/apps/job/urls.py @@ -86,6 +86,11 @@ kanban_view_api.FetchJobsByColumnAPIView.as_view(), name="api_fetch_jobs_by_column", ), + path( + "jobs/kanban-changes/", + kanban_view_api.KanbanChangesAPIView.as_view(), + name="api_kanban_changes", + ), path( "jobs/status-values/", kanban_view_api.FetchStatusValuesAPIView.as_view(), diff --git a/apps/job/views/__init__.py b/apps/job/views/__init__.py index 2fbcbf9a7..c1a210fbf 100644 --- a/apps/job/views/__init__.py +++ b/apps/job/views/__init__.py @@ -92,6 +92,7 @@ FetchJobsAPIView, FetchJobsByColumnAPIView, FetchStatusValuesAPIView, + KanbanChangesAPIView, ReorderJobAPIView, UpdateJobStatusAPIView, ) @@ -150,6 +151,7 @@ "JobSummaryRestView", "JobTimelineRestView", "JobUndoChangeRestView", + "KanbanChangesAPIView", "LabourSubtypeListView", "LabourSubtypeManageDetailView", "LabourSubtypeManageListCreateView", diff --git a/apps/job/views/job_rest_views.py b/apps/job/views/job_rest_views.py index 75c9f5f86..10fedf483 100644 --- a/apps/job/views/job_rest_views.py +++ b/apps/job/views/job_rest_views.py @@ -28,6 +28,7 @@ from rest_framework.views import APIView from apps.accounts.models import Staff +from apps.job.etag import generate_job_etag from apps.job.models import Job, JobDeltaRejection from apps.job.permissions import IsOfficeStaff from apps.job.serializers.job_serializer import ( @@ -59,6 +60,7 @@ JobRestService, PreconditionFailed, ) +from apps.workflow.etag import if_none_match_satisfied from apps.workflow.models import CompanyDefaults from apps.workflow.services.error_persistence import persist_app_error from apps.workflow.utils import parse_pagination_params @@ -114,42 +116,35 @@ def handle_service_error(self, error: Exception) -> Response: error_message = str(error) - # PreconditionFailed covers DeltaValidationError, which subclasses it. if isinstance(error, PreconditionFailed): - # ETag mismatch -> Optimistic concurrency conflict - error_response = { - "error": "Precondition failed (ETag mismatch). Reload the job and retry." - } - error_serializer = JobRestErrorResponseSerializer(error_response) - return Response( - error_serializer.data, status=status.HTTP_412_PRECONDITION_FAILED + response_status = status.HTTP_412_PRECONDITION_FAILED + response_message = ( + "Precondition failed (ETag mismatch). Reload the job and retry." ) - if isinstance(error, (Http404, NotFound)): - error_response = {"error": "Resource not found"} - error_serializer = JobRestErrorResponseSerializer(error_response) - return Response(error_serializer.data, status=status.HTTP_404_NOT_FOUND) - if isinstance(error, IntegrityError): - # Handle database constraint violations (duplicates) - error_response = { - "error": "Duplicate event prevented by database constraint" + elif isinstance(error, (Http404, NotFound)): + response_status = status.HTTP_404_NOT_FOUND + response_message = error_message + elif isinstance(error, IntegrityError): + response_status = status.HTTP_409_CONFLICT + response_message = error_message + elif isinstance(error, PermissionError): + response_status = status.HTTP_403_FORBIDDEN + response_message = error_message + elif isinstance(error, ValueError): + response_status = status.HTTP_400_BAD_REQUEST + response_message = error_message + else: + logger.error("Unhandled error: %s", error) + response_status = status.HTTP_500_INTERNAL_SERVER_ERROR + response_message = error_message + + error_serializer = JobRestErrorResponseSerializer( + { + "error": response_message, + "details": {"error_id": app_error.id}, } - error_serializer = JobRestErrorResponseSerializer(error_response) - return Response(error_serializer.data, status=status.HTTP_409_CONFLICT) - if isinstance(error, PermissionError): - error_response = {"error": error_message} - error_serializer = JobRestErrorResponseSerializer(error_response) - return Response(error_serializer.data, status=status.HTTP_403_FORBIDDEN) - if isinstance(error, ValueError): - error_response = {"error": error_message} - error_serializer = JobRestErrorResponseSerializer(error_response) - return Response(error_serializer.data, status=status.HTTP_400_BAD_REQUEST) - - logger.exception(f"Unhandled error: {error}") - error_response = {"error": "Internal server error"} - error_serializer = JobRestErrorResponseSerializer(error_response) - return Response( - error_serializer.data, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) + return Response(error_serializer.data, status=response_status) def check_request_debounce( self, request, operation_key: str, debounce_seconds: int = 2 @@ -177,38 +172,19 @@ def check_request_debounce( return False # Allow - outside debounce period # === Optimistic Concurrency (ETag) helpers === - def _normalize_etag(self, etag: str | None) -> str | None: - """Normalize an ETag/If-Match/If-None-Match value for comparison.""" - if not etag: - return None - val = etag.strip() - if val.startswith("W/"): - val = val[2:].strip() - if len(val) >= 2 and ( - (val[0] == '"' and val[-1] == '"') or (val[0] == "'" and val[-1] == "'") - ): - val = val[1:-1] - return val - def _gen_job_etag(self, job: Job) -> str: - """Generate a weak ETag for a Job based on its last update timestamp.""" - try: - ts_ms = int(job.updated_at.timestamp() * 1000) - except Exception: - ts_ms = 0 - return f'W/"job:{job.id}:{ts_ms}"' + """Generate a strong ETag for a Job based on its last update timestamp.""" + return generate_job_etag(job) def _get_if_match(self, request) -> str | None: - """Extract normalized If-Match header value.""" - header = request.headers.get("If-Match") or request.META.get("HTTP_IF_MATCH") - return self._normalize_etag(header) if header else None + """Extract the raw If-Match header for service-layer comparison.""" + return request.headers.get("If-Match") or request.META.get("HTTP_IF_MATCH") def _get_if_none_match(self, request) -> str | None: - """Extract normalized If-None-Match header value.""" - header = request.headers.get("If-None-Match") or request.META.get( + """Extract the raw If-None-Match header.""" + return request.headers.get("If-None-Match") or request.META.get( "HTTP_IF_NONE_MATCH" ) - return self._normalize_etag(header) if header else None def _precondition_required_response(self) -> Response: """Return 428 when If-Match is required but missing.""" @@ -351,7 +327,7 @@ def get(self, request, job_id): if ( if_none_match and current_etag - and self._normalize_etag(current_etag) == if_none_match + and if_none_match_satisfied(if_none_match, current_etag) ): resp = Response(status=status.HTTP_304_NOT_MODIFIED) return self._set_etag(resp, current_etag) @@ -604,7 +580,7 @@ def get(self, request, job_id): if ( if_none_match and current_etag - and self._normalize_etag(current_etag) == if_none_match + and if_none_match_satisfied(if_none_match, current_etag) ): resp = Response(status=status.HTTP_304_NOT_MODIFIED) return self._set_etag(resp, current_etag) @@ -663,6 +639,10 @@ def post(self, request, job_id): } """ try: + if_match = self._get_if_match(request) + if not if_match: + return self._precondition_required_response() + # Debounce check - prevent rapid requests debounce_key = f"add_event:{job_id}" if self.check_request_debounce(request, debounce_key, debounce_seconds=2): @@ -706,33 +686,10 @@ def post(self, request, job_id): error_serializer = JobRestErrorResponseSerializer(error_response) return Response(error_serializer.data, status=status.HTTP_409_CONFLICT) - # Require If-Match for optimistic concurrency control on event creation - if_match = self._get_if_match(request) - if not if_match: - return self._precondition_required_response() - - # Verify company ETag against current job version - try: - job_for_etag = Job.objects.only("id", "updated_at").get(id=job_id) - current_etag_norm = self._normalize_etag( - self._gen_job_etag(job_for_etag) - ) - if current_etag_norm != if_match: - error_response = { - "error": "Precondition failed (ETag mismatch). Reload the job and retry." - } - error_serializer = JobRestErrorResponseSerializer(error_response) - return Response( - error_serializer.data, - status=status.HTTP_412_PRECONDITION_FAILED, - ) - except Job.DoesNotExist: - error_response = {"error": "Resource not found"} - error_serializer = JobRestErrorResponseSerializer(error_response) - return Response(error_serializer.data, status=status.HTTP_404_NOT_FOUND) - # Create event via service - result = JobRestService.add_job_event(job_id, description, request.user) + result = JobRestService.add_job_event( + job_id, description, request.user, if_match + ) # Set duplicate prevention cache (5 minutes) cache.set(duplicate_check_key, True, 300) @@ -908,7 +865,7 @@ def get(self, request, job_id): # Conditional GET using ETag if_none_match = self._get_if_none_match(request) - if if_none_match and self._normalize_etag(current_etag) == if_none_match: + if if_none_match and if_none_match_satisfied(if_none_match, current_etag): resp = Response(status=status.HTTP_304_NOT_MODIFIED) return self._set_etag(resp, current_etag) @@ -950,7 +907,7 @@ def get(self, request, job_id): job = Job.objects.only("id", "updated_at").get(id=job_id) current_etag = self._gen_job_etag(job) inm = self._get_if_none_match(request) - if inm and self._normalize_etag(current_etag) == inm: + if inm and if_none_match_satisfied(inm, current_etag): resp = Response(status=status.HTTP_304_NOT_MODIFIED) return self._set_etag(resp, current_etag) @@ -992,7 +949,7 @@ def get(self, request, job_id): job = Job.objects.only("id", "updated_at").get(id=job_id) current_etag = self._gen_job_etag(job) inm = self._get_if_none_match(request) - if inm and self._normalize_etag(current_etag) == inm: + if inm and if_none_match_satisfied(inm, current_etag): resp = Response(status=status.HTTP_304_NOT_MODIFIED) return self._set_etag(resp, current_etag) @@ -1033,7 +990,7 @@ def get(self, request, job_id): job = Job.objects.only("id", "updated_at").get(id=job_id) current_etag = self._gen_job_etag(job) inm = self._get_if_none_match(request) - if inm and self._normalize_etag(current_etag) == inm: + if inm and if_none_match_satisfied(inm, current_etag): resp = Response(status=status.HTTP_304_NOT_MODIFIED) return self._set_etag(resp, current_etag) @@ -1444,7 +1401,7 @@ def get(self, request, job_id): raise ValueError(f"Job with id {job_id} not found") from exc if_none_match = self._get_if_none_match(request) - if if_none_match and self._normalize_etag(current_etag) == if_none_match: + if if_none_match and if_none_match_satisfied(if_none_match, current_etag): resp = Response(status=status.HTTP_304_NOT_MODIFIED) return self._set_etag(resp, current_etag) diff --git a/apps/job/views/kanban_view_api.py b/apps/job/views/kanban_view_api.py index 9c1bb9a88..8b51e0bfc 100644 --- a/apps/job/views/kanban_view_api.py +++ b/apps/job/views/kanban_view_api.py @@ -23,6 +23,7 @@ FetchStatusValuesResponseSerializer, JobReorderSerializer, JobStatusUpdateSerializer, + KanbanChangesResponseSerializer, KanbanErrorResponseSerializer, KanbanSuccessResponseSerializer, ) @@ -538,3 +539,62 @@ def get(self, request: Request, column_id: str) -> Response: return Response( error_serializer.data, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) + + +class KanbanChangesAPIView(APIView): + """Return changed Kanban cards after an opaque Job dataset version.""" + + permission_classes = [IsAuthenticated] + serializer_class = KanbanChangesResponseSerializer + + @extend_schema( + operation_id="getKanbanChanges", + parameters=[ + OpenApiParameter( + name="after", + type=str, + location=OpenApiParameter.QUERY, + required=True, + description="Opaque previous kanban dataset version", + ) + ], + responses={ + 200: KanbanChangesResponseSerializer, + 400: KanbanErrorResponseSerializer, + }, + ) + def get(self, request: Request) -> Response: + after = request.query_params.get("after") + if after is None: + return Response( + {"success": False, "error": "after is required"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + try: + changes = KanbanService.get_kanban_changes(after) + response_data = { + "success": True, + "jobs": KanbanService.serialize_jobs_for_api(changes.jobs), + "removed_job_ids": changes.removed_job_ids, + "full_refresh_required": changes.full_refresh_required, + } + serializer = KanbanChangesResponseSerializer(data=response_data) + serializer.is_valid(raise_exception=True) + return Response(serializer.data) + except ValueError as exc: + app_error = persist_app_error(exc) + error_serializer = KanbanErrorResponseSerializer( + { + "success": False, + "error": str(exc), + "details": {"error_id": app_error.id}, + } + ) + return Response( + error_serializer.data, + status=status.HTTP_400_BAD_REQUEST, + ) + except Exception as exc: + _persist_unexpected_error(exc) + raise diff --git a/apps/purchasing/__init__.py b/apps/purchasing/__init__.py index cdeb407c7..5dcad7a61 100644 --- a/apps/purchasing/__init__.py +++ b/apps/purchasing/__init__.py @@ -8,7 +8,7 @@ from django.apps import apps if apps.ready: - from .etag import generate_po_etag, normalize_etag + from .etag import generate_po_etag from .models import ( PurchaseOrder, PurchaseOrderEvent, @@ -47,6 +47,7 @@ PurchaseOrderLineSerializer, PurchaseOrderLineUpdateSerializer, PurchaseOrderListSerializer, + PurchaseOrderMutationErrorResponseSerializer, PurchaseOrderPDFResponseSerializer, PurchaseOrderUpdateResponseSerializer, PurchaseOrderUpdateSerializer, @@ -113,6 +114,7 @@ "PurchaseOrderLineSerializer", "PurchaseOrderLineUpdateSerializer", "PurchaseOrderListSerializer", + "PurchaseOrderMutationErrorResponseSerializer", "PurchaseOrderPDFResponseSerializer", "PurchaseOrderSupplierQuote", "PurchaseOrderUpdateResponseSerializer", @@ -135,7 +137,6 @@ "SupplierSearchResultSerializer", "enqueue_stock_metadata_parse", "generate_po_etag", - "normalize_etag", "stock_metadata_incomplete", "stock_metadata_parse_eligible", ] diff --git a/apps/purchasing/etag.py b/apps/purchasing/etag.py index 43f78d4f1..b7e0e26fb 100644 --- a/apps/purchasing/etag.py +++ b/apps/purchasing/etag.py @@ -1,30 +1,11 @@ -"""Helper utilities for Purchase Order ETag handling.""" +"""Purchase Order ETag generation.""" from __future__ import annotations -from typing import Optional - from apps.purchasing.models import PurchaseOrder - - -def normalize_etag(etag: Optional[str]) -> Optional[str]: - """Normalize an ETag header value for comparison.""" - if not etag: - return None - val = etag.strip() - if val.startswith("W/"): - val = val[2:].strip() - if len(val) >= 2 and ( - (val[0] == '"' and val[-1] == '"') or (val[0] == "'" and val[-1] == "'") - ): - val = val[1:-1] - return val or None +from apps.workflow.etag import generate_updated_at_etag def generate_po_etag(po: PurchaseOrder) -> str: - """Generate a weak ETag for a purchase order based on last modification time.""" - try: - ts_ms = int(po.updated_at.timestamp() * 1000) - except Exception: - ts_ms = 0 - return f'W/"po:{po.id}:{ts_ms}"' + """Generate a strong ETag for a Purchase Order.""" + return generate_updated_at_etag("po", po.id, po.updated_at) diff --git a/apps/purchasing/serializers.py b/apps/purchasing/serializers.py index 270e33f6a..0b8334f0a 100644 --- a/apps/purchasing/serializers.py +++ b/apps/purchasing/serializers.py @@ -12,6 +12,7 @@ PurchaseOrderLine, Stock, ) +from apps.workflow.serializers import AppErrorResponseSerializer class SupplierPriceStatusItemSerializer(serializers.Serializer): @@ -463,6 +464,12 @@ class PurchasingErrorResponseSerializer(serializers.Serializer): ) +class PurchaseOrderMutationErrorResponseSerializer(AppErrorResponseSerializer): + """Exception-derived error response for PO mutations and receipts.""" + + success = serializers.BooleanField(required=False, default=False) + + # Purchase Order Email and PDF serializers class PurchaseOrderEmailSerializer(serializers.Serializer): """Serializer for purchase order email generation request""" diff --git a/apps/purchasing/services/delivery_receipt_service.py b/apps/purchasing/services/delivery_receipt_service.py index 9f2a990c4..76a87fcfc 100644 --- a/apps/purchasing/services/delivery_receipt_service.py +++ b/apps/purchasing/services/delivery_receipt_service.py @@ -9,13 +9,14 @@ from django.utils import timezone from apps.job.models import CostLine, CostSet, Job -from apps.purchasing.etag import generate_po_etag, normalize_etag +from apps.purchasing.etag import generate_po_etag from apps.purchasing.exceptions import PreconditionFailedError from apps.purchasing.models import PurchaseOrder, PurchaseOrderLine, Stock from apps.purchasing.tasks import ( enqueue_stock_metadata_parse, stock_metadata_parse_eligible, ) +from apps.workflow.etag import if_match_satisfied from apps.workflow.models.company_defaults import CompanyDefaults from apps.workflow.services.error_persistence import persist_app_error from apps.workflow.services.validation import to_decimal @@ -306,7 +307,7 @@ def process_delivery_receipt( line_allocations: dict, staff, *, - expected_etag: str | None = None, + expected_etag: str, ) -> PurchaseOrder: """ Process a delivery receipt: @@ -319,20 +320,16 @@ def process_delivery_receipt( logger.info("Starting delivery receipt processing for PO ID: %s", purchase_order_id) logger.debug("Received line_allocations: %s", line_allocations) - STOCK_HOLDING_JOB_ID = Stock.get_stock_holding_job().id - run_id = f"dr-{uuid.uuid4()}" try: with transaction.atomic(): po, lines_by_id = _load_po_and_lines(purchase_order_id, line_allocations) - expected_normalized = ( - normalize_etag(expected_etag) if expected_etag else None - ) - current_etag = normalize_etag(generate_po_etag(po)) - if expected_normalized is not None and expected_normalized != current_etag: + current_etag = generate_po_etag(po) + if not if_match_satisfied(expected_etag, current_etag): raise PreconditionFailedError( "Purchase order modified since it was fetched." ) + stock_holding_job_id = Stock.get_stock_holding_job().id jobs_by_id = _load_jobs(line_allocations) if po.status not in ("submitted", "partially_received", "fully_received"): @@ -381,7 +378,7 @@ def process_delivery_receipt( qty = alloc["quantity"] retail_rate_pct = alloc["retail_rate_pct"] - if str(job.id) == str(STOCK_HOLDING_JOB_ID): + if str(job.id) == str(stock_holding_job_id): _create_stock_from_allocation( purchase_order=po, line=line, @@ -409,22 +406,11 @@ def process_delivery_receipt( ) return po - except DeliveryReceiptValidationError: - # Let DRF/view layer convert to proper 4xx; message already specific - logger.exception( - "Validation Error processing delivery receipt for PO %s", purchase_order_id - ) - raise - except PurchaseOrder.DoesNotExist: - logger.exception( - "PO %s not found during delivery receipt processing", purchase_order_id - ) - raise - except Exception as e: - persist_app_error(e) + except Exception as exc: + persist_app_error(exc) logger.exception( - "Unexpected error processing delivery receipt for PO %s: %s", + "Error processing delivery receipt for PO %s: %s", purchase_order_id, - str(e), + str(exc), ) raise diff --git a/apps/purchasing/services/purchasing_rest_service.py b/apps/purchasing/services/purchasing_rest_service.py index 9d46c04e3..1c33f526c 100644 --- a/apps/purchasing/services/purchasing_rest_service.py +++ b/apps/purchasing/services/purchasing_rest_service.py @@ -16,7 +16,7 @@ from apps.company.models import Supplier, SupplierPickupAddress from apps.job.models.costing import CostLine from apps.job.models.job import Job -from apps.purchasing.etag import generate_po_etag, normalize_etag +from apps.purchasing.etag import generate_po_etag from apps.purchasing.exceptions import PreconditionFailedError from apps.purchasing.models import PurchaseOrder, PurchaseOrderLine, Stock from apps.purchasing.services.delivery_receipt_service import ( @@ -27,6 +27,7 @@ enqueue_stock_metadata_parse, stock_metadata_parse_eligible, ) +from apps.workflow.etag import if_match_satisfied from apps.workflow.models import CompanyDefaults logger = logging.getLogger(__name__) @@ -413,10 +414,8 @@ def update_purchase_order( data: Dict[str, Any], *, staff, - expected_etag: str | None = None, + expected_etag: str, ) -> PurchaseOrder: - expected_normalized = normalize_etag(expected_etag) if expected_etag else None - with transaction.atomic(): try: po = ( @@ -428,8 +427,8 @@ def update_purchase_order( except PurchaseOrder.DoesNotExist as exc: raise Http404(f"PurchaseOrder {po_id} not found") from exc - current_etag = normalize_etag(generate_po_etag(po)) - if expected_normalized is not None and expected_normalized != current_etag: + current_etag = generate_po_etag(po) + if not if_match_satisfied(expected_etag, current_etag): raise PreconditionFailedError( "Purchase order modified since it was fetched." ) diff --git a/apps/purchasing/tests/test_purchase_order_etags.py b/apps/purchasing/tests/test_purchase_order_etags.py new file mode 100644 index 000000000..9db8ba23a --- /dev/null +++ b/apps/purchasing/tests/test_purchase_order_etags.py @@ -0,0 +1,100 @@ +"""Purchase-order mutations must enforce full-precision optimistic concurrency.""" + +from datetime import timedelta + +from apps.purchasing.etag import generate_po_etag +from apps.purchasing.models import PurchaseOrder +from apps.testing import BaseAPITestCase +from apps.workflow.models import AppError + + +class PurchaseOrderETagTests(BaseAPITestCase): + def setUp(self) -> None: + super().setUp() + self.client.force_authenticate(self.test_staff) + self.purchase_order = PurchaseOrder.objects.create( + po_number="PO-ETAG-1", + created_by=self.test_staff, + ) + self.detail_url = f"/api/purchasing/purchase-orders/{self.purchase_order.id}/" + + def _current_etag(self) -> str: + response = self.client.get(self.detail_url) + self.assertEqual(response.status_code, 200) + return response["ETag"] + + def test_patch_requires_if_match(self) -> None: + response = self.client.patch(self.detail_url, {}, format="json") + + self.assertEqual(response.status_code, 428) + + def test_patch_rejects_a_stale_etag(self) -> None: + stale_etag = self._current_etag() + self.purchase_order.reference = "Concurrent edit" + self.purchase_order.save(update_fields=["reference", "updated_at"]) + + response = self.client.patch( + self.detail_url, + {"reference": "Overwriting edit"}, + format="json", + HTTP_IF_MATCH=stale_etag, + ) + + self.assertEqual(response.status_code, 412) + self.assertIn("error_id", response.json()["details"]) + self.purchase_order.refresh_from_db() + self.assertEqual(self.purchase_order.reference, "Concurrent edit") + + def test_delivery_receipt_requires_if_match(self) -> None: + response = self.client.post( + "/api/purchasing/delivery-receipts/", + { + "purchase_order_id": str(self.purchase_order.id), + "allocations": {}, + }, + format="json", + ) + + self.assertEqual(response.status_code, 428) + + def test_delivery_receipt_rejects_a_stale_etag(self) -> None: + stale_etag = self._current_etag() + self.purchase_order.reference = "Concurrent receipt edit" + self.purchase_order.save(update_fields=["reference", "updated_at"]) + + response = self.client.post( + "/api/purchasing/delivery-receipts/", + { + "purchase_order_id": str(self.purchase_order.id), + "allocations": {}, + }, + format="json", + HTTP_IF_MATCH=stale_etag, + ) + + self.assertEqual(response.status_code, 412) + self.assertIn("error_id", response.json()["details"]) + self.assertEqual(AppError.objects.count(), 1) + + def test_patch_rejects_a_weak_if_match_tag(self) -> None: + current_etag = self._current_etag() + + response = self.client.patch( + self.detail_url, + {"reference": "Weak edit"}, + format="json", + HTTP_IF_MATCH=f"W/{current_etag}", + ) + + self.assertEqual(response.status_code, 412) + self.purchase_order.refresh_from_db() + self.assertIsNone(self.purchase_order.reference) + + def test_etag_distinguishes_changes_within_one_millisecond(self) -> None: + first_timestamp = self.purchase_order.updated_at + self.purchase_order.updated_at = first_timestamp + timedelta(microseconds=100) + + later_etag = generate_po_etag(self.purchase_order) + self.purchase_order.updated_at = first_timestamp + + self.assertNotEqual(generate_po_etag(self.purchase_order), later_etag) diff --git a/apps/purchasing/views/purchasing_rest_views.py b/apps/purchasing/views/purchasing_rest_views.py index 0e37b1267..34c12d2f6 100644 --- a/apps/purchasing/views/purchasing_rest_views.py +++ b/apps/purchasing/views/purchasing_rest_views.py @@ -15,7 +15,7 @@ from apps.job.models import Job from apps.job.models.costing import CostLine -from apps.purchasing.etag import generate_po_etag, normalize_etag +from apps.purchasing.etag import generate_po_etag from apps.purchasing.models import ( PurchaseOrder, PurchaseOrderEvent, @@ -44,6 +44,7 @@ PurchaseOrderEventsResponseSerializer, PurchaseOrderLastNumberResponseSerializer, PurchaseOrderListSerializer, + PurchaseOrderMutationErrorResponseSerializer, PurchaseOrderPDFResponseSerializer, PurchaseOrderUpdateResponseSerializer, PurchaseOrderUpdateSerializer, @@ -55,7 +56,10 @@ AllocationDeletionError, AllocationService, ) -from apps.purchasing.services.delivery_receipt_service import process_delivery_receipt +from apps.purchasing.services.delivery_receipt_service import ( + DeliveryReceiptValidationError, + process_delivery_receipt, +) from apps.purchasing.services.purchase_order_email_service import ( create_purchase_order_email, ) @@ -66,23 +70,38 @@ PreconditionFailedError, PurchasingRestService, ) +from apps.workflow.etag import if_none_match_satisfied from apps.workflow.services.error_persistence import persist_app_error logger = logging.getLogger(__name__) +def _purchase_order_error_response( + exc: Exception, + response_status: int, +) -> Response: + """Persist and serialize an exception-derived PO error response.""" + app_error = persist_app_error(exc) + serializer = PurchaseOrderMutationErrorResponseSerializer( + { + "success": False, + "error": str(exc), + "details": {"error_id": app_error.id}, + } + ) + return Response(serializer.data, status=response_status) + + class PurchaseOrderETagMixin: """Shared helpers for purchase order ETag handling.""" def _get_if_match(self, request): - header = request.headers.get("If-Match") or request.META.get("HTTP_IF_MATCH") - return normalize_etag(header) if header else None + return request.headers.get("If-Match") or request.META.get("HTTP_IF_MATCH") def _get_if_none_match(self, request): - header = request.headers.get("If-None-Match") or request.META.get( + return request.headers.get("If-None-Match") or request.META.get( "HTTP_IF_NONE_MATCH" ) - return normalize_etag(header) if header else None def _precondition_required_response(self): error = {"error": "Missing If-Match header (precondition required)"} @@ -459,7 +478,7 @@ def get(self, request, po_id): ) etag = generate_po_etag(po) if_none_match = self._get_if_none_match(request) - if if_none_match and if_none_match == normalize_etag(etag): + if if_none_match and if_none_match_satisfied(if_none_match, etag): return Response(status=status.HTTP_304_NOT_MODIFIED) response = Response(serializer.data) self._set_etag(response, etag) @@ -505,26 +524,25 @@ def patch(self, request, po_id): logger.warning( "ETag mismatch updating purchase order %s: %s", po_id, str(exc) ) - return Response( - {"error": "Precondition failed (ETag mismatch). Reload and retry."}, - status=status.HTTP_412_PRECONDITION_FAILED, + return _purchase_order_error_response( + exc, + status.HTTP_412_PRECONDITION_FAILED, ) except ValidationError as exc: - persist_app_error(exc) logger.warning( "Validation error updating purchase order %s: %s", po_id, str(exc) ) - return Response( - {"error": "Validation error", "details": str(exc)}, - status=status.HTTP_400_BAD_REQUEST, + return _purchase_order_error_response( + exc, + status.HTTP_400_BAD_REQUEST, ) - except Exception as e: - logger.error(f"Error updating purchase order {id}: {str(e)}") - return Response( - {"error": "Failed to update purchase order", "details": str(e)}, - status=status.HTTP_500_INTERNAL_SERVER_ERROR, + except Exception as exc: + logger.exception("Error updating purchase order %s", po_id) + return _purchase_order_error_response( + exc, + status.HTTP_500_INTERNAL_SERVER_ERROR, ) @@ -541,7 +559,10 @@ class DeliveryReceiptRestView(PurchaseOrderETagMixin, APIView): @extend_schema( responses={ status.HTTP_200_OK: DeliveryReceiptResponseSerializer, - status.HTTP_400_BAD_REQUEST: DeliveryReceiptResponseSerializer, + status.HTTP_400_BAD_REQUEST: PurchaseOrderMutationErrorResponseSerializer, + status.HTTP_404_NOT_FOUND: PurchaseOrderMutationErrorResponseSerializer, + status.HTTP_412_PRECONDITION_FAILED: PurchaseOrderMutationErrorResponseSerializer, + status.HTTP_500_INTERNAL_SERVER_ERROR: PurchaseOrderMutationErrorResponseSerializer, } ) def post(self, request): @@ -584,22 +605,22 @@ def post(self, request): purchase_order_id, str(exc), ) - response_data = { - "success": False, - "error": "Precondition failed (ETag mismatch). Reload and retry.", - } - response_serializer = DeliveryReceiptResponseSerializer(response_data) - return Response( - response_serializer.data, - status=status.HTTP_412_PRECONDITION_FAILED, + return _purchase_order_error_response( + exc, + status.HTTP_412_PRECONDITION_FAILED, ) - except Exception as e: - logger.error(f"Error processing delivery receipt: {str(e)}") - response_data = {"success": False, "error": str(e)} - response_serializer = DeliveryReceiptResponseSerializer(response_data) - return Response( - response_serializer.data, status=status.HTTP_400_BAD_REQUEST + except DeliveryReceiptValidationError as exc: + return _purchase_order_error_response(exc, status.HTTP_400_BAD_REQUEST) + + except PurchaseOrder.DoesNotExist as exc: + return _purchase_order_error_response(exc, status.HTTP_404_NOT_FOUND) + + except Exception as exc: + logger.exception("Error processing delivery receipt") + return _purchase_order_error_response( + exc, + status.HTTP_500_INTERNAL_SERVER_ERROR, ) diff --git a/apps/workflow/__init__.py b/apps/workflow/__init__.py index 405847d8b..2c283d47d 100644 --- a/apps/workflow/__init__.py +++ b/apps/workflow/__init__.py @@ -20,6 +20,12 @@ service_api_key_required, ) from .context_processors import debug_mode + from .etag import ( + generate_updated_at_etag, + if_match_satisfied, + if_none_match_satisfied, + updated_at_etag_value, + ) from .exception_handlers import custom_exception_handler from .extensions import CookieJWTScheme from .middleware import ( @@ -38,7 +44,9 @@ AIProviderCreateUpdateSerializer, AIProviderSerializer, AppErrorDetailResponseSerializer, + AppErrorDetailsSerializer, AppErrorListResponseSerializer, + AppErrorResponseSerializer, AppErrorSerializer, CompanyDefaultsSchemaSerializer, CompanyDefaultsSerializer, @@ -104,7 +112,9 @@ "AIProviderTypes", "AccessLoggingMiddleware", "AppErrorDetailResponseSerializer", + "AppErrorDetailsSerializer", "AppErrorListResponseSerializer", + "AppErrorResponseSerializer", "AppErrorSerializer", "CompanyDefaultsSchemaSerializer", "CompanyDefaultsSerializer", @@ -165,13 +175,17 @@ "custom_exception_handler", "debug_mode", "extract_messages", + "generate_updated_at_etag", "get_machine_id", + "if_match_satisfied", + "if_none_match_satisfied", "is_valid_invoice_number", "is_valid_uuid", "parse_pagination_params", "process_xero_webhook_event", "purge_old_session_replays_task", "service_api_key_required", + "updated_at_etag_value", "validate_webhook_signature", "xero_30_day_sync_task", "xero_heartbeat_task", diff --git a/apps/workflow/etag.py b/apps/workflow/etag.py new file mode 100644 index 000000000..5354ce761 --- /dev/null +++ b/apps/workflow/etag.py @@ -0,0 +1,50 @@ +"""Shared HTTP ETag helpers for updated-at versioned resources.""" + +from datetime import UTC, datetime +from uuid import UUID + +from django.utils import timezone +from django.utils.http import parse_etags, quote_etag + + +def updated_at_etag_value( + resource: str, + resource_id: UUID, + updated_at: datetime, +) -> str: + """Return the opaque value for a full-precision resource ETag.""" + if timezone.is_naive(updated_at): + raise ValueError("ETag timestamps must be timezone-aware") + + timestamp = ( + updated_at.astimezone(UTC) + .isoformat(timespec="microseconds") + .replace("+00:00", "Z") + ) + return f"{resource}:{resource_id}:{timestamp}" + + +def generate_updated_at_etag( + resource: str, + resource_id: UUID, + updated_at: datetime, +) -> str: + """Return a strong ETag suitable for both If-Match and If-None-Match.""" + return quote_etag(updated_at_etag_value(resource, resource_id, updated_at)) + + +def if_match_satisfied(header: str, current_etag: str) -> bool: + """Apply the application's exact-current-version mutation contract.""" + return current_etag in parse_etags(header) + + +def if_none_match_satisfied(header: str, current_etag: str) -> bool: + """Apply RFC weak comparison semantics for conditional GET requests.""" + candidates = parse_etags(header) + if "*" in candidates: + return True + + current_weak_value = current_etag.removeprefix("W/") + return any( + candidate.removeprefix("W/") == current_weak_value for candidate in candidates + ) diff --git a/apps/workflow/serializers.py b/apps/workflow/serializers.py index dee7a5053..c1ba382dc 100644 --- a/apps/workflow/serializers.py +++ b/apps/workflow/serializers.py @@ -19,6 +19,19 @@ from .models.settings_metadata import COMPANY_DEFAULTS_READ_ONLY_FIELDS +class AppErrorDetailsSerializer(serializers.Serializer): + """Reference to the persisted failure backing an API error response.""" + + error_id = serializers.UUIDField() + + +class AppErrorResponseSerializer(serializers.Serializer): + """Shared exception-derived API error contract.""" + + error = serializers.CharField() + details = AppErrorDetailsSerializer(required=False) + + def _build_logo_url(instance: CompanyDefaults, field_name: str) -> str | None: """Return the logo path relative to the site root. diff --git a/apps/workflow/tests/test_data_versions_view.py b/apps/workflow/tests/test_data_versions_view.py index dfd1da864..8572d460a 100644 --- a/apps/workflow/tests/test_data_versions_view.py +++ b/apps/workflow/tests/test_data_versions_view.py @@ -101,12 +101,15 @@ def test_get_returns_dict_with_dataset_keys(auth_client, db): body = resp.json() assert "stock" in body assert "kanban" in body + assert "kanban_related" in body assert "crm_calls" in body assert isinstance(body["stock"], str) assert isinstance(body["kanban"], str) + assert isinstance(body["kanban_related"], str) assert isinstance(body["crm_calls"], str) assert body["stock"] assert body["kanban"] + assert body["kanban_related"] assert body["crm_calls"] @@ -198,7 +201,7 @@ def test_assigning_staff_changes_kanban_version( assert before != after -def test_related_display_changes_change_kanban_version( +def test_related_display_changes_only_change_kanban_related_version( auth_client, office_staff, kanban_prerequisites ): company = _client(name="Original Company") @@ -208,23 +211,25 @@ def test_related_display_changes_change_kanban_version( person=person, ) _job(office_staff, company=company, person=person) - before = auth_client.get("/api/data-versions/").json()["kanban"] + before = auth_client.get("/api/data-versions/").json() person.name = "Updated Person" person.save(update_fields=["name"]) - after = auth_client.get("/api/data-versions/").json()["kanban"] - assert before != after + after = auth_client.get("/api/data-versions/").json() + assert before["kanban"] == after["kanban"] + assert before["kanban_related"] != after["kanban_related"] -def test_company_partial_save_changes_kanban_version( +def test_company_partial_save_only_changes_kanban_related_version( auth_client: APIClient, office_staff: Staff, kanban_prerequisites: None ) -> None: company = _client(name="Original Company") _job(office_staff, company=company) - before = auth_client.get("/api/data-versions/").json()["kanban"] + before = auth_client.get("/api/data-versions/").json() company.name = "Updated Company" company.save(update_fields=["name"]) - after = auth_client.get("/api/data-versions/").json()["kanban"] - assert before != after + after = auth_client.get("/api/data-versions/").json() + assert before["kanban"] == after["kanban"] + assert before["kanban_related"] != after["kanban_related"] def test_creating_phone_call_changes_crm_calls_version( diff --git a/apps/workflow/tests/test_etag.py b/apps/workflow/tests/test_etag.py new file mode 100644 index 000000000..78b8ec6b6 --- /dev/null +++ b/apps/workflow/tests/test_etag.py @@ -0,0 +1,37 @@ +"""Shared ETag helpers must implement the application's HTTP contracts.""" + +from datetime import UTC, datetime +from uuid import uuid4 + +from django.test import SimpleTestCase + +from apps.workflow.etag import ( + generate_updated_at_etag, + if_match_satisfied, + if_none_match_satisfied, +) + + +class UpdatedAtETagTests(SimpleTestCase): + def setUp(self) -> None: + self.etag = generate_updated_at_etag( + "job", + uuid4(), + datetime(2026, 7, 30, 12, 0, 0, 123456, tzinfo=UTC), + ) + + def test_generates_a_strong_etag(self) -> None: + self.assertTrue(self.etag.startswith('"job:')) + self.assertFalse(self.etag.startswith("W/")) + + def test_if_match_accepts_the_exact_current_tag_in_a_header_list(self) -> None: + self.assertTrue(if_match_satisfied(f'"other", {self.etag}', self.etag)) + + def test_if_match_rejects_weak_wildcard_and_malformed_tags(self) -> None: + self.assertFalse(if_match_satisfied(f"W/{self.etag}", self.etag)) + self.assertFalse(if_match_satisfied("*", self.etag)) + self.assertFalse(if_match_satisfied("not-an-etag", self.etag)) + + def test_if_none_match_uses_weak_comparison_and_wildcard_semantics(self) -> None: + self.assertTrue(if_none_match_satisfied(f"W/{self.etag}", self.etag)) + self.assertTrue(if_none_match_satisfied("*", self.etag)) diff --git a/apps/workflow/views/data_versions_view.py b/apps/workflow/views/data_versions_view.py index deb836e16..08516d28b 100644 --- a/apps/workflow/views/data_versions_view.py +++ b/apps/workflow/views/data_versions_view.py @@ -25,6 +25,7 @@ from apps.accounts.models import Staff from apps.company.models import Company, CompanyPersonLink, Person from apps.crm.models import PhoneCallRecord, PhoneCallRecording +from apps.job.kanban_version import KanbanDatasetVersion from apps.job.models import Job from apps.purchasing.models import Stock from apps.workflow.services.error_persistence import persist_app_error @@ -41,12 +42,24 @@ def _stock_version() -> str: def _kanban_version() -> str: - # Tracks inputs read by KanbanService.serialize_job_for_api() plus column - # membership/order. This is deliberately conservative: false positives - # only trigger a reload, while false negatives would serve stale cards. + """Track Job rows for incremental Kanban card reconciliation.""" + aggregate = Job.objects.aggregate( + updated=Max("updated_at"), + created=Max("created_at"), + count=Count("id"), + ) + version = KanbanDatasetVersion.from_values( + updated_at=aggregate["updated"], + created_at=aggregate["created"], + count=aggregate["count"], + ) + return version.encode() + + +def _kanban_related_version() -> str: + """Conservatively track related display inputs used by Kanban cards.""" return "|".join( [ - _model_version(Job, "updated_at"), _model_version(Company, "django_updated_at"), _model_version(CompanyPersonLink, "updated_at"), _model_version(Person, "updated_at"), @@ -73,6 +86,7 @@ def _crm_calls_version() -> str: DATASET_VERSION_PROVIDERS: Dict[str, Callable[[], str]] = { "stock": _stock_version, "kanban": _kanban_version, + "kanban_related": _kanban_related_version, "crm_calls": _crm_calls_version, } diff --git a/docs/urls/job.md b/docs/urls/job.md index e7b9b6fdb..4d1062d4e 100644 --- a/docs/urls/job.md +++ b/docs/urls/job.md @@ -78,6 +78,7 @@ | `/jobs/fetch-all/` | `kanban_view_api.FetchAllJobsAPIView` | `jobs:api_fetch_all_jobs` | Fetch all jobs for Kanban board - API endpoint. | | `/jobs/fetch-by-column//` | `kanban_view_api.FetchJobsByColumnAPIView` | `jobs:api_fetch_jobs_by_column` | Fetch jobs by kanban column using new categorization system. | | `/jobs/fetch//` | `kanban_view_api.FetchJobsAPIView` | `jobs:api_fetch_jobs` | Fetch jobs by status with optional search - API endpoint. | +| `/jobs/kanban-changes/` | `kanban_view_api.KanbanChangesAPIView` | `jobs:api_kanban_changes` | Return changed Kanban cards after an opaque Job dataset version. | | `/jobs/status-choices/` | `job_rest_views.JobStatusChoicesRestView` | `jobs:job_status_choices_rest` | REST view for Job status choices. | | `/jobs/status-values/` | `kanban_view_api.FetchStatusValuesAPIView` | `jobs:api_fetch_status_values` | Return available status values for Kanban - API endpoint. | | `/jobs/weekly-metrics/` | `job_rest_views.WeeklyMetricsRestView` | `jobs:weekly_metrics_rest` | REST view for fetching weekly metrics. | diff --git a/frontend/schema.yml b/frontend/schema.yml index 6bf59f665..825140ab5 100644 --- a/frontend/schema.yml +++ b/frontend/schema.yml @@ -5166,6 +5166,34 @@ paths: schema: $ref: '#/components/schemas/FetchJobsResponse' description: '' + /api/job/jobs/kanban-changes/: + get: + operationId: getKanbanChanges + description: Return changed Kanban cards after an opaque Job dataset version. + parameters: + - in: query + name: after + schema: + type: string + description: Opaque previous kanban dataset version + required: true + tags: + - job + security: + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/KanbanChangesResponse' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/KanbanErrorResponse' + description: '' /api/job/jobs/status-choices/: get: operationId: job_jobs_status_choices_retrieve @@ -7222,7 +7250,25 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/DeliveryReceiptResponse' + $ref: '#/components/schemas/PurchaseOrderMutationErrorResponse' + description: '' + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/PurchaseOrderMutationErrorResponse' + description: '' + '412': + content: + application/json: + schema: + $ref: '#/components/schemas/PurchaseOrderMutationErrorResponse' + description: '' + '500': + content: + application/json: + schema: + $ref: '#/components/schemas/PurchaseOrderMutationErrorResponse' description: '' /api/purchasing/jobs/: get: @@ -10382,6 +10428,15 @@ components: - id - message - timestamp + AppErrorDetails: + type: object + description: Reference to the persisted failure backing an API error response. + properties: + error_id: + type: string + format: uuid + required: + - error_id AppErrorListResponse: type: object description: Serializer for paginated AppError list response. @@ -10751,9 +10806,12 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email nullable: true + oneOf: + - type: string + format: email + - type: string + maxLength: 0 phone: type: string nullable: true @@ -10870,22 +10928,28 @@ components: description: Prefix for purchase order numbers (e.g., PO-, JO-) maxLength: 10 master_quote_template_url: - type: string - format: uri nullable: true description: URL to the master Google Sheets quote template - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 master_quote_template_id: type: string nullable: true description: Google Sheets ID for the quote template maxLength: 100 gdrive_quotes_folder_url: - type: string - format: uri nullable: true description: URL to the Google Drive folder for storing quotes - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 gdrive_quotes_folder_id: type: string nullable: true @@ -11047,17 +11111,23 @@ components: description: Country name maxLength: 100 company_email: - type: string - format: email nullable: true description: Company contact email address - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 company_url: - type: string - format: uri nullable: true description: Company website URL - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 test_company_name: type: string nullable: true @@ -11257,22 +11327,28 @@ components: description: Prefix for purchase order numbers (e.g., PO-, JO-) maxLength: 10 master_quote_template_url: - type: string - format: uri nullable: true description: URL to the master Google Sheets quote template - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 master_quote_template_id: type: string nullable: true description: Google Sheets ID for the quote template maxLength: 100 gdrive_quotes_folder_url: - type: string - format: uri nullable: true description: URL to the Google Drive folder for storing quotes - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 gdrive_quotes_folder_id: type: string nullable: true @@ -11429,17 +11505,23 @@ components: description: Country name maxLength: 100 company_email: - type: string - format: email nullable: true description: Company contact email address - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 company_url: - type: string - format: uri nullable: true description: Company website URL - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 test_company_name: type: string nullable: true @@ -11773,9 +11855,12 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email nullable: true + oneOf: + - type: string + format: email + - type: string + maxLength: 0 phone: type: string nullable: true @@ -11862,8 +11947,11 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email + oneOf: + - type: string + format: email + - type: string + maxLength: 0 phone: type: string nullable: true @@ -12583,11 +12671,14 @@ components: type: string kanban: type: string + kanban_related: + type: string crm_calls: type: string required: - crm_calls - kanban + - kanban_related - stock Day: type: object @@ -13769,10 +13860,13 @@ components: type: number format: double online_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 required: - amount_due - date @@ -15284,6 +15378,8 @@ components: properties: error: type: string + details: + $ref: '#/components/schemas/AppErrorDetails' required: - error JobStatusChoicesResponse: @@ -15934,6 +16030,30 @@ components: - kpi_daily_gp_green - kpi_daily_gp_target - kpi_daily_shop_hours_percentage + KanbanChangesResponse: + type: object + description: Serializer for incremental Kanban freshness reconciliation. + properties: + success: + type: boolean + default: true + jobs: + type: array + items: + $ref: '#/components/schemas/KanbanColumnJob' + removed_job_ids: + type: array + items: + type: string + format: uuid + full_refresh_required: + type: boolean + error: + type: string + required: + - full_refresh_required + - jobs + - removed_job_ids KanbanColumnJob: type: object description: |- @@ -16036,11 +16156,13 @@ components: type: object description: Serializer for error kanban operation response. properties: + error: + type: string + details: + $ref: '#/components/schemas/AppErrorDetails' success: type: boolean default: false - error: - type: string required: - error KanbanJob: @@ -16319,8 +16441,11 @@ components: description: Serializer for link quote sheet request data. properties: template_url: - type: string - format: uri + oneOf: + - type: string + format: uri + - type: string + maxLength: 0 LinkQuoteSheetResponse: type: object description: Serializer for link quote sheet response. @@ -17132,22 +17257,28 @@ components: description: Prefix for purchase order numbers (e.g., PO-, JO-) maxLength: 10 master_quote_template_url: - type: string - format: uri nullable: true description: URL to the master Google Sheets quote template - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 master_quote_template_id: type: string nullable: true description: Google Sheets ID for the quote template maxLength: 100 gdrive_quotes_folder_url: - type: string - format: uri nullable: true description: URL to the Google Drive folder for storing quotes - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 gdrive_quotes_folder_id: type: string nullable: true @@ -17304,17 +17435,23 @@ components: description: Country name maxLength: 100 company_email: - type: string - format: email nullable: true description: Company contact email address - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 company_url: - type: string - format: uri nullable: true description: Company website URL - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 test_company_name: type: string nullable: true @@ -17409,8 +17546,11 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email + oneOf: + - type: string + format: email + - type: string + maxLength: 0 phone: type: string nullable: true @@ -17681,10 +17821,13 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 PatchedPhoneEndpointRequest: type: object properties: @@ -17716,10 +17859,13 @@ components: recording_deletion_enabled: type: boolean base_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 username: type: string writeOnly: true @@ -18539,10 +18685,13 @@ components: type: string maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 is_active: type: boolean created_at: @@ -18582,10 +18731,13 @@ components: type: string maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 PersonIdentityUpdateRequest: type: object properties: @@ -18594,10 +18746,13 @@ components: minLength: 1 maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 PersonSummary: type: object properties: @@ -18609,10 +18764,13 @@ components: type: string maxLength: 255 email: - type: string - format: email nullable: true - maxLength: 254 + oneOf: + - type: string + format: email + maxLength: 254 + - type: string + maxLength: 0 is_active: type: boolean primary_phone: @@ -19083,10 +19241,13 @@ components: recording_deletion_enabled: type: boolean base_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 has_username: type: boolean readOnly: true @@ -19367,10 +19528,13 @@ components: description: Work site location maxLength: 500 google_doc_url: - type: string - format: uri description: URL to edit the document in Google Docs - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 job_number: type: string readOnly: true @@ -19669,10 +19833,13 @@ components: format: date nullable: true online_url: - type: string - format: uri nullable: true - maxLength: 500 + oneOf: + - type: string + format: uri + maxLength: 500 + - type: string + maxLength: 0 xero_id: type: string format: uuid @@ -20134,6 +20301,19 @@ components: - status - supplier - supplier_id + PurchaseOrderMutationErrorResponse: + type: object + description: Exception-derived error response for PO mutations and receipts. + properties: + error: + type: string + details: + $ref: '#/components/schemas/AppErrorDetails' + success: + type: boolean + default: false + required: + - error PurchaseOrderUpdate: type: object description: Serializer for updating purchase orders. @@ -20213,10 +20393,13 @@ components: type: number format: double online_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 required: - date - id @@ -20337,10 +20520,13 @@ components: description: Google Drive file ID maxLength: 100 sheet_url: - type: string - format: uri nullable: true - maxLength: 500 + oneOf: + - type: string + format: uri + maxLength: 500 + - type: string + maxLength: 0 tab: type: string nullable: true @@ -24257,9 +24443,12 @@ components: format: uuid description: The Xero UUID of the created/modified document. online_url: - type: string - format: uri description: Direct link to the document in Xero. + oneOf: + - type: string + format: uri + - type: string + maxLength: 0 messages: type: array items: @@ -24371,10 +24560,13 @@ components: status: $ref: '#/components/schemas/InvoiceStatusEnum' online_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 required: - number XeroInvoiceCreateModeEnum: @@ -24503,10 +24695,13 @@ components: status: $ref: '#/components/schemas/QuoteStatusEnum' online_url: - type: string - format: uri nullable: true - maxLength: 200 + oneOf: + - type: string + format: uri + maxLength: 200 + - type: string + maxLength: 0 XeroQuoteCreateRequest: type: object description: |- diff --git a/frontend/src/api/generated/api.ts b/frontend/src/api/generated/api.ts index 3a4c76662..1a2b63300 100644 --- a/frontend/src/api/generated/api.ts +++ b/frontend/src/api/generated/api.ts @@ -676,7 +676,7 @@ const CompanyPerson = z.object({ }) const CompanyPersonCreateRequest = z.object({ name: z.string().min(1).max(255), - email: z.string().email().nullish(), + email: z.union([z.string(), z.string()]).nullish(), phone: z.string().nullish(), position: z.string().max(255).nullish(), notes: z.string().nullish(), @@ -730,7 +730,7 @@ const SupplierSearchAliasCreateRequest = z.object({ const CompanyUpdateRequest = z .object({ name: z.string().min(1).max(255), - email: z.string().email(), + email: z.union([z.string(), z.string()]), phone: z.string().nullable(), address: z.string(), is_account_customer: z.boolean(), @@ -745,7 +745,7 @@ const CompanyUpdateResponse = z.object({ const PatchedCompanyUpdateRequest = z .object({ name: z.string().min(1).max(255), - email: z.string().email(), + email: z.union([z.string(), z.string()]), phone: z.string().nullable(), address: z.string(), is_account_customer: z.boolean(), @@ -800,7 +800,7 @@ const PatchedContactMethodRequest = z .partial() const CompanyCreateRequest = z.object({ name: z.string().min(1).max(255), - email: z.string().email().nullish(), + email: z.union([z.string(), z.string()]).nullish(), phone: z.string().nullish(), address: z.string().nullish(), is_account_customer: z.boolean().optional().default(true), @@ -914,9 +914,9 @@ const CompanyDefaults = z.object({ starting_job_number: z.number().int().gte(-2147483648).lte(2147483647).optional(), starting_po_number: z.number().int().gte(-2147483648).lte(2147483647).optional(), po_prefix: z.string().max(10).optional(), - master_quote_template_url: z.string().max(200).url().nullish(), + master_quote_template_url: z.union([z.string(), z.string()]).nullish(), master_quote_template_id: z.string().max(100).nullish(), - gdrive_quotes_folder_url: z.string().max(200).url().nullish(), + gdrive_quotes_folder_url: z.union([z.string(), z.string()]).nullish(), gdrive_quotes_folder_id: z.string().max(100).nullish(), google_shared_drive_id: z.string().max(100).nullish(), gdrive_how_we_work_folder_id: z.string().max(100).nullish(), @@ -953,8 +953,8 @@ const CompanyDefaults = z.object({ city: z.string().max(100).nullish(), post_code: z.string().max(20).nullish(), country: z.string().max(100).optional(), - company_email: z.string().max(254).email().nullish(), - company_url: z.string().max(200).url().nullish(), + company_email: z.union([z.string(), z.string()]).nullish(), + company_url: z.union([z.string(), z.string()]).nullish(), test_company_name: z.string().max(255).nullish(), kpi_daily_billable_hours_green: z.number().gt(-1000).lt(1000).optional(), kpi_daily_billable_hours_amber: z.number().gt(-1000).lt(1000).optional(), @@ -980,9 +980,9 @@ const CompanyDefaultsRequest = z.object({ starting_job_number: z.number().int().gte(-2147483648).lte(2147483647).optional(), starting_po_number: z.number().int().gte(-2147483648).lte(2147483647).optional(), po_prefix: z.string().min(1).max(10).optional(), - master_quote_template_url: z.string().max(200).url().nullish(), + master_quote_template_url: z.union([z.string(), z.string()]).nullish(), master_quote_template_id: z.string().max(100).nullish(), - gdrive_quotes_folder_url: z.string().max(200).url().nullish(), + gdrive_quotes_folder_url: z.union([z.string(), z.string()]).nullish(), gdrive_quotes_folder_id: z.string().max(100).nullish(), google_shared_drive_id: z.string().max(100).nullish(), gdrive_how_we_work_folder_id: z.string().max(100).nullish(), @@ -1017,8 +1017,8 @@ const CompanyDefaultsRequest = z.object({ city: z.string().max(100).nullish(), post_code: z.string().max(20).nullish(), country: z.string().min(1).max(100).optional(), - company_email: z.string().max(254).email().nullish(), - company_url: z.string().max(200).url().nullish(), + company_email: z.union([z.string(), z.string()]).nullish(), + company_url: z.union([z.string(), z.string()]).nullish(), test_company_name: z.string().max(255).nullish(), kpi_daily_billable_hours_green: z.number().gt(-1000).lt(1000).optional(), kpi_daily_billable_hours_amber: z.number().gt(-1000).lt(1000).optional(), @@ -1045,9 +1045,9 @@ const PatchedCompanyDefaultsRequest = z starting_job_number: z.number().int().gte(-2147483648).lte(2147483647), starting_po_number: z.number().int().gte(-2147483648).lte(2147483647), po_prefix: z.string().min(1).max(10), - master_quote_template_url: z.string().max(200).url().nullable(), + master_quote_template_url: z.union([z.string(), z.string()]).nullable(), master_quote_template_id: z.string().max(100).nullable(), - gdrive_quotes_folder_url: z.string().max(200).url().nullable(), + gdrive_quotes_folder_url: z.union([z.string(), z.string()]).nullable(), gdrive_quotes_folder_id: z.string().max(100).nullable(), google_shared_drive_id: z.string().max(100).nullable(), gdrive_how_we_work_folder_id: z.string().max(100).nullable(), @@ -1082,8 +1082,8 @@ const PatchedCompanyDefaultsRequest = z city: z.string().max(100).nullable(), post_code: z.string().max(20).nullable(), country: z.string().min(1).max(100), - company_email: z.string().max(254).email().nullable(), - company_url: z.string().max(200).url().nullable(), + company_email: z.union([z.string(), z.string()]).nullable(), + company_url: z.union([z.string(), z.string()]).nullable(), test_company_name: z.string().max(255).nullable(), kpi_daily_billable_hours_green: z.number().gt(-1000).lt(1000), kpi_daily_billable_hours_amber: z.number().gt(-1000).lt(1000), @@ -1218,7 +1218,7 @@ const PhoneProviderSettings = z.object({ id: z.number().int(), downloads_enabled: z.boolean().optional(), recording_deletion_enabled: z.boolean().optional(), - base_url: z.string().max(200).url().nullish(), + base_url: z.union([z.string(), z.string()]).nullish(), has_username: z.boolean(), has_password: z.boolean(), account_code: z.string().max(100).optional(), @@ -1229,7 +1229,7 @@ const PatchedPhoneProviderSettingsRequest = z .object({ downloads_enabled: z.boolean(), recording_deletion_enabled: z.boolean(), - base_url: z.string().max(200).url().nullable(), + base_url: z.union([z.string(), z.string()]).nullable(), username: z.string(), password: z.string(), account_code: z.string().max(100), @@ -1238,6 +1238,7 @@ const PatchedPhoneProviderSettingsRequest = z const DataVersions = z.object({ stock: z.string(), kanban: z.string(), + kanban_related: z.string(), crm_calls: z.string(), }) const CompanyDefaultsJobDetail = z.object({ @@ -1511,7 +1512,11 @@ const JobCreateResponse = z.object({ job_number: z.number().int(), message: z.string(), }) -const JobRestErrorResponse = z.object({ error: z.string() }) +const AppErrorDetails = z.object({ error_id: z.string().uuid() }) +const JobRestErrorResponse = z.object({ + error: z.string(), + details: AppErrorDetails.optional(), +}) const CostSetKindEnum = z.enum(['estimate', 'quote', 'actual']) const CostSetSummary = z.object({ cost: z.number(), @@ -1545,7 +1550,7 @@ const SpeedQualityTradeoffEnum = z.enum(['fast', 'normal', 'quality']) const QuoteSpreadsheet = z.object({ id: z.string().uuid(), sheet_id: z.string().max(100), - sheet_url: z.string().max(500).url().nullish(), + sheet_url: z.union([z.string(), z.string()]).nullish(), tab: z.string().max(100).nullish(), job_id: z.string(), job_number: z.number().int(), @@ -1559,7 +1564,7 @@ const Quote = z.object({ date: z.string(), total_excl_tax: z.number(), total_incl_tax: z.number(), - online_url: z.string().max(200).url().nullish(), + online_url: z.union([z.string(), z.string()]).nullish(), }) const InvoiceStatusEnum = z.enum(['DRAFT', 'SUBMITTED', 'AUTHORISED', 'DELETED', 'VOIDED', 'PAID']) const Invoice = z.object({ @@ -1573,18 +1578,18 @@ const Invoice = z.object({ total_incl_tax: z.number(), amount_due: z.number(), tax: z.number().optional(), - online_url: z.string().max(200).url().nullish(), + online_url: z.union([z.string(), z.string()]).nullish(), }) const XeroQuote = z .object({ status: QuoteStatusEnum, - online_url: z.string().max(200).url().nullable(), + online_url: z.union([z.string(), z.string()]).nullable(), }) .partial() const XeroInvoice = z.object({ number: z.string().max(255), status: InvoiceStatusEnum.optional(), - online_url: z.string().max(200).url().nullish(), + online_url: z.union([z.string(), z.string()]).nullish(), }) const RdtiTypeEnum = z.enum(['non_rd', 'core_rd', 'supporting_rd']) const BlankEnum = z.unknown() @@ -1916,8 +1921,9 @@ const KanbanSuccessResponse = z.object({ message: z.string(), }) const KanbanErrorResponse = z.object({ - success: z.boolean().optional().default(false), error: z.string(), + details: AppErrorDetails.optional(), + success: z.boolean().optional().default(false), }) const CostSetSummaryOnly = z.object({ id: z.string(), @@ -2035,7 +2041,9 @@ const ApplyQuoteErrorResponse = z.object({ error: z.string(), }) const QuoteSyncErrorResponse = z.object({ error: z.string() }) -const LinkQuoteSheetRequest = z.object({ template_url: z.string().url() }).partial() +const LinkQuoteSheetRequest = z + .object({ template_url: z.union([z.string(), z.string()]) }) + .partial() const LinkQuoteSheetResponse = z.object({ sheet_url: z.string().url(), sheet_id: z.string(), @@ -2184,6 +2192,13 @@ const FetchJobsResponse = z error: z.string(), }) .partial() +const KanbanChangesResponse = z.object({ + success: z.boolean().optional().default(true), + jobs: z.array(KanbanColumnJob), + removed_job_ids: z.array(z.string().uuid()), + full_refresh_required: z.boolean(), + error: z.string().optional(), +}) const JobStatusChoicesResponse = z.object({ statuses: z.object({}).partial().passthrough(), }) @@ -2510,7 +2525,7 @@ const PersonCompanySummary = z.object({ const PersonSummary = z.object({ id: z.string().uuid(), name: z.string().max(255), - email: z.string().max(254).email().nullish(), + email: z.union([z.string(), z.string()]).nullish(), is_active: z.boolean(), primary_phone: z.string(), companies: z.array(PersonCompanySummary), @@ -2525,7 +2540,7 @@ const PaginatedPersonSummaryList = z.object({ const PersonDetail = z.object({ id: z.string().uuid(), name: z.string().max(255), - email: z.string().max(254).email().nullish(), + email: z.union([z.string(), z.string()]).nullish(), is_active: z.boolean(), created_at: z.string().datetime({ offset: true }), updated_at: z.string().datetime({ offset: true }), @@ -2536,19 +2551,19 @@ const PersonDetail = z.object({ const PersonIdentityUpdateRequest = z .object({ name: z.string().min(1).max(255), - email: z.string().max(254).email().nullable(), + email: z.union([z.string(), z.string()]).nullable(), }) .partial() const PersonIdentityUpdate = z .object({ name: z.string().max(255), - email: z.string().max(254).email().nullable(), + email: z.union([z.string(), z.string()]).nullable(), }) .partial() const PatchedPersonIdentityUpdateRequest = z .object({ name: z.string().min(1).max(255), - email: z.string().max(254).email().nullable(), + email: z.union([z.string(), z.string()]).nullable(), }) .partial() const CompanyLinkWriteRequest = z @@ -2667,7 +2682,7 @@ const ProcedureList = z.object({ document_number: z.string().max(50).nullish(), title: z.string().max(255), site_location: z.string().max(500).optional(), - google_doc_url: z.string().max(200).url().optional(), + google_doc_url: z.union([z.string(), z.string()]).optional(), job_number: z.string().nullable(), tags: z.unknown().optional(), status: ProcedureStatusEnum.optional(), @@ -2803,6 +2818,11 @@ const DeliveryReceiptResponse = z.object({ success: z.boolean(), error: z.string().optional(), }) +const PurchaseOrderMutationErrorResponse = z.object({ + error: z.string(), + details: AppErrorDetails.optional(), + success: z.boolean().optional().default(false), +}) const PurchasingJobsResponse = z.object({ jobs: z.array(JobForPurchasing), total_count: z.number().int(), @@ -2947,7 +2967,7 @@ const PurchaseOrderDetail = z.object({ status: PurchaseOrderDetailStatusEnum.optional(), order_date: z.string().optional(), expected_delivery: z.string().nullish(), - online_url: z.string().max(500).url().nullish(), + online_url: z.union([z.string(), z.string()]).nullish(), xero_id: z.string().uuid().nullish(), pickup_address_id: z.string().uuid().nullable(), created_by_id: z.string().uuid().nullable(), @@ -3692,7 +3712,7 @@ const XeroInvoiceCreateRequest = z.object({ const XeroDocumentSuccessResponse = z.object({ success: z.boolean().optional().default(true), xero_id: z.string().uuid(), - online_url: z.string().url().optional(), + online_url: z.union([z.string(), z.string()]).optional(), messages: z.array(z.string()).optional(), company: z.string().optional(), total_excl_tax: z.number().gt(-10000000000).lt(10000000000).optional(), @@ -3887,6 +3907,7 @@ export const schemas = { ArchiveJobsResponse, JobCreateRequest, JobCreateResponse, + AppErrorDetails, JobRestErrorResponse, CostSetKindEnum, CostSetSummary, @@ -3984,6 +4005,7 @@ export const schemas = { KanbanColumnJob, FetchJobsByColumnResponse, FetchJobsResponse, + KanbanChangesResponse, JobStatusChoicesResponse, FetchStatusValuesResponse, WeeklyMetrics, @@ -4070,6 +4092,7 @@ export const schemas = { DeliveryReceiptLineRequest, DeliveryReceiptRequest, DeliveryReceiptResponse, + PurchaseOrderMutationErrorResponse, PurchasingJobsResponse, ProductMapping, ProductMappingListResponse, @@ -6438,7 +6461,7 @@ POST /job/rest/cost_lines/<cost_line_id>/approve`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -6512,7 +6535,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/link/`, { name: 'body', type: 'Body', - schema: z.object({ template_url: z.string().url() }).partial(), + schema: LinkQuoteSheetRequest, }, { name: 'id', @@ -6604,7 +6627,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -6630,7 +6653,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -6651,7 +6674,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -6672,7 +6695,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -6801,7 +6824,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -6847,7 +6870,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -6868,7 +6891,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -6894,15 +6917,15 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, { status: 409, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, { status: 429, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7102,7 +7125,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7123,7 +7146,7 @@ POST /job/rest/jobs/<uuid:pk>/quote/preview/`, errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7325,7 +7348,7 @@ Expected JSON: errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7351,7 +7374,7 @@ Expected JSON: errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7421,7 +7444,7 @@ Expected JSON: errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7442,7 +7465,7 @@ Expected JSON: errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7468,7 +7491,7 @@ Expected JSON: errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7633,7 +7656,7 @@ Expected JSON: errors: [ { status: 400, - schema: z.object({ error: z.string() }), + schema: JobRestErrorResponse, }, ], }, @@ -7742,6 +7765,27 @@ Expected JSON: ], response: FetchJobsResponse, }, + { + method: 'get', + path: '/api/job/jobs/kanban-changes/', + alias: 'getKanbanChanges', + description: `Return changed Kanban cards after an opaque Job dataset version.`, + requestFormat: 'json', + parameters: [ + { + name: 'after', + type: 'Query', + schema: z.string(), + }, + ], + response: KanbanChangesResponse, + errors: [ + { + status: 400, + schema: KanbanErrorResponse, + }, + ], + }, { method: 'get', path: '/api/job/jobs/status-choices/', @@ -9126,7 +9170,19 @@ Concurrency is controlled in this endpoint (ETag/If-Match).`, errors: [ { status: 400, - schema: DeliveryReceiptResponse, + schema: PurchaseOrderMutationErrorResponse, + }, + { + status: 404, + schema: PurchaseOrderMutationErrorResponse, + }, + { + status: 412, + schema: PurchaseOrderMutationErrorResponse, + }, + { + status: 500, + schema: PurchaseOrderMutationErrorResponse, }, ], }, diff --git a/frontend/src/composables/__tests__/useDataFreshness.test.ts b/frontend/src/composables/__tests__/useDataFreshness.test.ts new file mode 100644 index 000000000..923b18aec --- /dev/null +++ b/frontend/src/composables/__tests__/useDataFreshness.test.ts @@ -0,0 +1,51 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' + +const { retrieveDataVersions } = vi.hoisted(() => ({ + retrieveDataVersions: vi.fn(), +})) + +vi.mock('@/api/client', () => ({ + api: { + data_versions_retrieve: retrieveDataVersions, + }, +})) + +import { dataFreshness } from '@/composables/useDataFreshness' + +describe('useDataFreshness', () => { + beforeEach(() => { + vi.clearAllMocks() + dataFreshness._resetForTesting() + }) + + it('passes the previous and current opaque versions to stale subscribers', async () => { + const onStale = vi.fn() + dataFreshness.subscribe('kanban', onStale) + retrieveDataVersions + .mockResolvedValueOnce({ kanban: 'version-1' }) + .mockResolvedValueOnce({ kanban: 'version-2' }) + + await dataFreshness.checkFreshness() + await dataFreshness.checkFreshness() + + expect(onStale).toHaveBeenCalledWith('version-1', 'version-2') + }) + + it('retries a version change when its subscriber fails', async () => { + const failure = new Error('incremental refresh failed') + const onStale = vi.fn().mockRejectedValueOnce(failure).mockResolvedValueOnce(undefined) + const consoleError = vi.spyOn(console, 'error').mockImplementation(() => undefined) + dataFreshness.subscribe('kanban', onStale) + retrieveDataVersions + .mockResolvedValueOnce({ kanban: 'version-1' }) + .mockResolvedValue({ kanban: 'version-2' }) + + await dataFreshness.checkFreshness() + await dataFreshness.checkFreshness() + await dataFreshness.checkFreshness() + + expect(onStale).toHaveBeenCalledTimes(2) + expect(consoleError).toHaveBeenCalled() + consoleError.mockRestore() + }) +}) diff --git a/frontend/src/composables/__tests__/useOptimizedKanban.test.ts b/frontend/src/composables/__tests__/useOptimizedKanban.test.ts index cbfceef28..a701c62ff 100644 --- a/frontend/src/composables/__tests__/useOptimizedKanban.test.ts +++ b/frontend/src/composables/__tests__/useOptimizedKanban.test.ts @@ -12,7 +12,9 @@ const { updateJobStatus, reorderJob, performAdvancedSearch, + getKanbanChanges, checkFreshness, + freshnessSubscribers, saveFeedback, kanbanColumnCache, kanbanJobsById, @@ -27,7 +29,12 @@ const { updateJobStatus: vi.fn(), reorderJob: vi.fn(), performAdvancedSearch: vi.fn(), + getKanbanChanges: vi.fn(), checkFreshness: vi.fn(), + freshnessSubscribers: new Map< + string, + (previousVersion: string, currentVersion: string) => void | Promise + >(), saveFeedback: { pending: vi.fn(), saving: vi.fn(), @@ -62,6 +69,7 @@ vi.mock('@/services/job.service', () => ({ tooltips: {}, }), performAdvancedSearch, + getKanbanChanges, updateJobStatus, reorderJob, }, @@ -141,12 +149,29 @@ vi.mock('@/stores/jobs', () => ({ }, setCurrentContext, setLoadingKanban, + setKanbanJob: (job: Record) => { + kanbanJobsById.set(String(job.id), job) + }, + removeKanbanJob: (jobId: string) => { + kanbanJobsById.delete(jobId) + }, + clearKanbanColumnCache: () => { + kanbanColumnCache.clear() + kanbanJobsById.clear() + }, }), })) vi.mock('../useDataFreshness', () => ({ dataFreshness: { checkFreshness, + subscribe: ( + key: string, + callback: (previousVersion: string, currentVersion: string) => void | Promise, + ) => { + freshnessSubscribers.set(key, callback) + return vi.fn() + }, }, })) @@ -236,7 +261,14 @@ describe('useOptimizedKanban search reconciliation', () => { route.query = {} kanbanColumnCache.clear() kanbanJobsById.clear() + freshnessSubscribers.clear() checkFreshness.mockResolvedValue(undefined) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [], + removed_job_ids: [], + full_refresh_required: false, + }) updateJobStatus.mockResolvedValue({ success: true }) reorderJob.mockResolvedValue({ success: true }) getJobsByColumn.mockImplementation(async (columnId: string) => { @@ -304,6 +336,428 @@ describe('useOptimizedKanban search reconciliation', () => { expect(kanban.getJobsByStatus.value('in_progress').map((job) => job.id)).toEqual(['job-1']) }) + it('merges a content-only freshness change without reloading any column', async () => { + const unchangedJob = buildKanbanJob({ id: 'job-2', name: 'Unchanged' }) + getJobsByColumn.mockImplementation(async (columnId: string) => { + if (columnId === 'in_progress') { + return { + success: true, + jobs: [buildKanbanJob(), unchangedJob], + total: 2, + filtered_count: 2, + has_more: false, + } + } + return { success: true, jobs: [], total: 0, filtered_count: 0, has_more: false } + }) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [buildKanbanJob({ name: 'Updated card', updated_at: '2026-05-15T00:00:00Z' })], + removed_job_ids: [], + full_refresh_required: false, + }) + + const kanban = await mountHarness() + getJobsByColumn.mockClear() + + await freshnessSubscribers.get('kanban')?.('old-version', 'new-version') + + expect(getKanbanChanges).toHaveBeenCalledWith('old-version') + expect(getJobsByColumn).not.toHaveBeenCalled() + expect(kanban.getJobsByStatus.value('in_progress').map((job) => job.name)).toEqual([ + 'Updated card', + 'Unchanged', + ]) + }) + + it('reconciles quick-search membership authoritatively after incremental changes', async () => { + const leavingJob = buildKanbanJob({ id: 'job-leaving', name: 'Kick plate' }) + const enteringJob = buildKanbanJob({ id: 'job-entering', name: 'Plain plate' }) + getJobsByColumn.mockImplementation(async (columnId: string) => { + if (columnId === 'in_progress') { + return { + success: true, + jobs: [leavingJob, enteringJob], + total: 2, + filtered_count: 2, + has_more: false, + } + } + return { success: true, jobs: [], total: 0, filtered_count: 0, has_more: false } + }) + performAdvancedSearch.mockResolvedValueOnce({ jobs: [leavingJob] }).mockResolvedValueOnce({ + jobs: [ + buildKanbanJob({ + id: 'job-entering', + name: 'Kick plate revision', + updated_at: '2026-05-15T00:00:00Z', + }), + ], + }) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [ + buildKanbanJob({ + id: 'job-leaving', + name: 'No longer matching', + updated_at: '2026-05-15T00:00:00Z', + }), + buildKanbanJob({ + id: 'job-entering', + name: 'Kick plate revision', + updated_at: '2026-05-15T00:00:00Z', + }), + ], + removed_job_ids: [], + full_refresh_required: false, + }) + + const kanban = await mountHarness() + kanban.searchQuery.value = 'kick' + await kanban.handleSearch() + await vi.advanceTimersByTimeAsync(300) + await flushPromises() + + expect(kanban.filteredJobs.value.map((job) => job.id)).toEqual(['job-leaving']) + + await freshnessSubscribers.get('kanban')?.('old-version', 'new-version') + + expect(performAdvancedSearch).toHaveBeenCalledTimes(2) + expect(kanban.filteredJobs.value.map((job) => job.id)).toEqual(['job-entering']) + }) + + it('keeps zero-result advanced search active and refreshes its membership', async () => { + const matchingJob = buildKanbanJob({ id: 'job-advanced', name: 'Advanced match' }) + performAdvancedSearch + .mockResolvedValueOnce({ jobs: [] }) + .mockResolvedValueOnce({ jobs: [matchingJob] }) + .mockResolvedValueOnce({ jobs: [] }) + .mockResolvedValueOnce({ jobs: [] }) + getKanbanChanges + .mockResolvedValueOnce({ + success: true, + jobs: [matchingJob], + removed_job_ids: [], + full_refresh_required: false, + }) + .mockResolvedValueOnce({ + success: true, + jobs: [], + removed_job_ids: [], + full_refresh_required: true, + }) + + const kanban = await mountHarness() + kanban.advancedFilters.value.name = 'Advanced' + await kanban.handleAdvancedSearch() + + expect(kanban.isSearchActive.value).toBe(true) + expect(kanban.getJobsByStatus.value('in_progress')).toEqual([]) + + await freshnessSubscribers.get('kanban')?.('version-1', 'version-2') + + expect(kanban.filteredJobs.value.map((job) => job.id)).toEqual(['job-advanced']) + + await freshnessSubscribers.get('kanban')?.('version-2', 'version-3') + await freshnessSubscribers.get('kanban_related')?.('related-1', 'related-2') + + expect(performAdvancedSearch).toHaveBeenCalledTimes(4) + expect(performAdvancedSearch).toHaveBeenLastCalledWith( + expect.objectContaining({ name: 'Advanced' }), + ) + expect(kanban.isSearchActive.value).toBe(true) + expect(kanban.getJobsByStatus.value('in_progress')).toEqual([]) + }) + + it('revalidates only the old and new columns for a structural freshness change', async () => { + const unchangedJob = buildKanbanJob({ id: 'job-2', name: 'Unchanged' }) + const archivedJob = buildKanbanJob({ + id: 'job-archived', + name: 'Archived', + status: 'archived', + status_key: 'archived', + }) + getJobsByColumn.mockImplementation(async (columnId: string) => { + if (columnId === 'in_progress') { + return { + success: true, + jobs: [buildKanbanJob(), unchangedJob], + total: 2, + filtered_count: 2, + has_more: false, + } + } + if (columnId === 'archived') { + return { + success: true, + jobs: [archivedJob], + total: 1, + filtered_count: 1, + has_more: false, + } + } + return { success: true, jobs: [], total: 0, filtered_count: 0, has_more: false } + }) + + const kanban = await mountHarness() + const movedJob = buildKanbanJob({ + status: 'draft', + status_key: 'draft', + priority: 200, + updated_at: '2026-05-15T00:00:00Z', + }) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [movedJob], + removed_job_ids: [], + full_refresh_required: false, + }) + getJobsByColumn.mockClear() + getJobsByColumn.mockImplementation(async (columnId: string) => { + if (columnId === 'draft') { + return { + success: true, + jobs: [movedJob], + total: 1, + filtered_count: 1, + has_more: false, + } + } + if (columnId === 'in_progress') { + return { + success: true, + jobs: [unchangedJob], + total: 1, + filtered_count: 1, + has_more: false, + } + } + throw new Error(`Unexpected revalidation of ${columnId}`) + }) + + await freshnessSubscribers.get('kanban')?.('old-version', 'new-version') + + expect(getJobsByColumn.mock.calls.map(([columnId]) => columnId).sort()).toEqual([ + 'draft', + 'in_progress', + ]) + expect(kanban.getJobsByStatus.value('draft').map((job) => job.id)).toEqual(['job-1']) + expect(kanban.getJobsByStatus.value('in_progress').map((job) => job.id)).toEqual(['job-2']) + expect(kanban.getJobsByStatus.value('archived').map((job) => job.id)).toEqual(['job-archived']) + }) + + it('revalidates only one column when priority changes within the same status', async () => { + const kanban = await mountHarness() + const reprioritizedJob = buildKanbanJob({ + priority: 200, + updated_at: '2026-05-15T00:00:00Z', + }) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [reprioritizedJob], + removed_job_ids: [], + full_refresh_required: false, + }) + getJobsByColumn.mockClear() + getJobsByColumn.mockResolvedValue({ + success: true, + jobs: [reprioritizedJob], + total: 1, + filtered_count: 1, + has_more: false, + }) + + await freshnessSubscribers.get('kanban')?.('old-version', 'new-version') + + expect(getJobsByColumn).toHaveBeenCalledOnce() + expect(getJobsByColumn).toHaveBeenCalledWith('in_progress') + expect(kanban.getJobsByStatus.value('in_progress')[0]?.priority).toBe(200) + }) + + it('rejects failed freshness revalidation so the same old token can be retried', async () => { + const kanban = await mountHarness() + const reprioritizedJob = buildKanbanJob({ + priority: 200, + updated_at: '2026-05-15T00:00:00Z', + }) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [reprioritizedJob], + removed_job_ids: [], + full_refresh_required: false, + }) + getJobsByColumn.mockRejectedValueOnce(new Error('column unavailable')).mockResolvedValueOnce({ + success: true, + jobs: [reprioritizedJob], + total: 1, + filtered_count: 1, + has_more: false, + }) + + const refresh = freshnessSubscribers.get('kanban') + await expect(refresh?.('old-version', 'new-version')).rejects.toThrow( + 'Failed to revalidate changed Kanban columns', + ) + await refresh?.('old-version', 'new-version') + + expect(getKanbanChanges).toHaveBeenNthCalledWith(1, 'old-version') + expect(getKanbanChanges).toHaveBeenNthCalledWith(2, 'old-version') + expect(kanban.getJobsByStatus.value('in_progress')[0]?.priority).toBe(200) + }) + + it('rejects an unsafe full refresh when any required column fails', async () => { + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [], + removed_job_ids: [], + full_refresh_required: true, + }) + await mountHarness() + getJobsByColumn.mockImplementation(async (columnId: string) => { + if (columnId === 'draft') { + throw new Error('draft unavailable') + } + return { success: true, jobs: [], total: 0, filtered_count: 0, has_more: false } + }) + + await expect( + freshnessSubscribers.get('kanban')?.('old-version', 'new-version'), + ).rejects.toThrow('Failed to reload Kanban after unsafe incremental response') + }) + + it('rejects freshness when authoritative quick-search reconciliation fails', async () => { + performAdvancedSearch + .mockResolvedValueOnce({ jobs: [buildKanbanJob()] }) + .mockRejectedValueOnce(new Error('search unavailable')) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [buildKanbanJob({ name: 'Changed card' })], + removed_job_ids: [], + full_refresh_required: false, + }) + + const kanban = await mountHarness() + kanban.searchQuery.value = 'kick' + await kanban.handleSearch() + await vi.advanceTimersByTimeAsync(300) + await flushPromises() + + await expect( + freshnessSubscribers.get('kanban')?.('old-version', 'new-version'), + ).rejects.toThrow('search unavailable') + }) + + it('queues a forced freshness load behind an in-flight column request', async () => { + const kanban = await mountHarness() + const pendingLoad = deferred<{ + success: boolean + jobs: ReturnType[] + total: number + filtered_count: number + has_more: boolean + }>() + const reprioritizedJob = buildKanbanJob({ + priority: 200, + updated_at: '2026-05-15T00:00:00Z', + }) + getJobsByColumn.mockReset() + getJobsByColumn.mockReturnValueOnce(pendingLoad.promise).mockResolvedValueOnce({ + success: true, + jobs: [reprioritizedJob], + total: 1, + filtered_count: 1, + has_more: false, + }) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [reprioritizedJob], + removed_job_ids: [], + full_refresh_required: false, + }) + + const ordinaryLoad = kanban.loadColumnJobs('in_progress', { force: true }) + const freshnessLoad = freshnessSubscribers.get('kanban')?.('old-version', 'new-version') + await flushPromises() + + expect(getJobsByColumn).toHaveBeenCalledOnce() + + pendingLoad.resolve({ + success: true, + jobs: [buildKanbanJob()], + total: 1, + filtered_count: 1, + has_more: false, + }) + await ordinaryLoad + await freshnessLoad + + expect(getJobsByColumn).toHaveBeenCalledTimes(2) + expect(kanban.getJobsByStatus.value('in_progress')[0]?.priority).toBe(200) + }) + + it('runs an unsafe full refresh while a backend search is still loading', async () => { + const pendingSearch = deferred<{ jobs: ReturnType[] }>() + performAdvancedSearch + .mockReturnValueOnce(pendingSearch.promise) + .mockResolvedValueOnce({ jobs: [buildKanbanJob()] }) + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [], + removed_job_ids: [], + full_refresh_required: true, + }) + + const kanban = await mountHarness() + kanban.searchQuery.value = 'kick' + await kanban.handleSearch() + await vi.advanceTimersByTimeAsync(300) + await flushPromises() + expect(kanban.isLoading.value).toBe(true) + getJobsByColumn.mockClear() + + await freshnessSubscribers.get('kanban')?.('old-version', 'new-version') + + expect(getJobsByColumn.mock.calls.map(([columnId]) => columnId).sort()).toEqual([ + 'archived', + 'draft', + 'in_progress', + ]) + pendingSearch.resolve({ jobs: [buildKanbanJob()] }) + await flushPromises() + }) + + it('force reloads every visible column when incremental reconciliation is unsafe', async () => { + getKanbanChanges.mockResolvedValue({ + success: true, + jobs: [], + removed_job_ids: [], + full_refresh_required: true, + }) + await mountHarness() + getJobsByColumn.mockClear() + + await freshnessSubscribers.get('kanban')?.('old-version', 'new-version') + + expect(getJobsByColumn.mock.calls.map(([columnId]) => columnId).sort()).toEqual([ + 'archived', + 'draft', + 'in_progress', + ]) + }) + + it('force reloads every visible column when related display data changes', async () => { + await mountHarness() + getJobsByColumn.mockClear() + + await freshnessSubscribers.get('kanban_related')?.('old-version', 'new-version') + + expect(getJobsByColumn.mock.calls.map(([columnId]) => columnId).sort()).toEqual([ + 'archived', + 'draft', + 'in_progress', + ]) + }) + it('shows immediate local matches, then reconciles with backend results', async () => { performAdvancedSearch.mockResolvedValue({ jobs: [ diff --git a/frontend/src/composables/useDataFreshness.ts b/frontend/src/composables/useDataFreshness.ts index 185b1a96f..3d0474c95 100644 --- a/frontend/src/composables/useDataFreshness.ts +++ b/frontend/src/composables/useDataFreshness.ts @@ -1,6 +1,6 @@ import { api } from '@/api/client' -type StaleCallback = () => void | Promise +type StaleCallback = (previousVersion: string, currentVersion: string) => void | Promise const knownVersions = new Map() const subscribers = new Map>() @@ -20,6 +20,9 @@ function subscribe(key: string, onStale: StaleCallback): () => void { bucket.add(onStale) return () => { bucket?.delete(onStale) + if (bucket?.size === 0) { + subscribers.delete(key) + } } } @@ -36,17 +39,25 @@ async function checkFreshness(): Promise { const fresh = (await api.data_versions_retrieve()) as Record for (const [key, version] of Object.entries(fresh)) { const previous = knownVersions.get(key) - knownVersions.set(key, version) - if (previous === undefined || previous === version) continue + if (previous === undefined) { + knownVersions.set(key, version) + continue + } + if (previous === version) continue const bucket = subscribers.get(key) if (!bucket) continue + let callbacksSucceeded = true for (const cb of bucket) { try { - await cb() + await cb(previous, version) } catch (err) { + callbacksSucceeded = false console.error(`useDataFreshness: stale callback for "${key}" threw`, err) } } + if (callbacksSucceeded) { + knownVersions.set(key, version) + } } } finally { inFlight = null diff --git a/frontend/src/composables/useOptimizedKanban.ts b/frontend/src/composables/useOptimizedKanban.ts index 6bb0e0f9b..af396d897 100644 --- a/frontend/src/composables/useOptimizedKanban.ts +++ b/frontend/src/composables/useOptimizedKanban.ts @@ -1,4 +1,4 @@ -import { ref, computed, reactive, onMounted, watch } from 'vue' +import { ref, computed, reactive, onMounted, onUnmounted, watch } from 'vue' import { useRouter, useRoute } from 'vue-router' import { useDebounceFn } from '@vueuse/core' import { jobService } from '../services/job.service' @@ -41,6 +41,8 @@ interface KanbanMoveSnapshot { movedJob: KanbanJob | null } +type SearchMode = 'none' | 'quick' | 'advanced' + export function useOptimizedKanban(onJobsLoaded?: () => void) { const router = useRouter() const route = useRoute() @@ -61,7 +63,12 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { const activeStaffFilters = ref([]) const advancedFilters = ref({ ...DEFAULT_ADVANCED_FILTERS }) const filteredJobs = ref([]) + const searchMode = ref( + typeof initialQuery === 'string' && initialQuery.trim() ? 'quick' : 'none', + ) let latestSearchRequestId = 0 + let loadingOperationCount = 0 + let kanbanLoadOperationCount = 0 let initialized = false let mounted = false let jobsLoadedCallbackPending = false @@ -69,6 +76,17 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { // Column-based state management const columnStates = reactive>({}) + const columnLoadQueues = new Map>() + + const beginLoadingOperation = (): void => { + loadingOperationCount += 1 + isLoading.value = true + } + + const endLoadingOperation = (): void => { + loadingOperationCount -= 1 + isLoading.value = loadingOperationCount > 0 + } // Watch URL for browser back/forward navigation watch( @@ -80,6 +98,7 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { if (parsed) { handleSearch() } else { + searchMode.value = 'none' filteredJobs.value = [] } } @@ -256,42 +275,54 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { const loadColumnJobs = async ( columnId: string, options: { force?: boolean } = {}, - ): Promise => { + ): Promise => { if (!columnStates[columnId]) { initializeColumnStates() } - const columnState = columnStates[columnId] - if (columnState.loading) return - - try { - columnState.loading = true - columnState.error = null + const performLoad = async (): Promise => { + const columnState = columnStates[columnId] + try { + columnState.loading = true + columnState.error = null - log(`Loading jobs for column: ${columnId}`) + log(`Loading jobs for column: ${columnId}`) - const data: KanbanColumnCacheEntry = await jobsStore.loadKanbanColumnWithCache( - columnId, - () => jobService.getJobsByColumn(columnId), - options, - ) - applyColumnData(columnId, data) + const data: KanbanColumnCacheEntry = await jobsStore.loadKanbanColumnWithCache( + columnId, + () => jobService.getJobsByColumn(columnId), + options, + ) + applyColumnData(columnId, data) - log(`Loaded ${data.jobIds.length} jobs for column: ${columnId}`) - } catch (err) { - columnState.error = err instanceof Error ? err.message : `Failed to load jobs for ${columnId}` - log(`Error loading jobs for column ${columnId}:`, err) + log(`Loaded ${data.jobIds.length} jobs for column: ${columnId}`) + return true + } catch (err) { + columnState.error = + err instanceof Error ? err.message : `Failed to load jobs for ${columnId}` + log(`Error loading jobs for column ${columnId}:`, err) + return false + } finally { + columnState.loading = false + } + } + const previousLoad = columnLoadQueues.get(columnId) + const queuedLoad = previousLoad ? previousLoad.then(performLoad) : performLoad() + columnLoadQueues.set(columnId, queuedLoad) + try { + return await queuedLoad } finally { - columnState.loading = false + if (columnLoadQueues.get(columnId) === queuedLoad) { + columnLoadQueues.delete(columnId) + } } } // Load all visible columns - const loadAllColumns = async (options: { force?: boolean } = {}): Promise => { - if (isLoading.value) return - + const loadAllColumns = async (options: { force?: boolean } = {}): Promise => { try { - isLoading.value = true + beginLoadingOperation() + kanbanLoadOperationCount += 1 error.value = null jobsStore.setCurrentContext('kanban') @@ -300,25 +331,134 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { const columns = KanbanCategorizationService.getAllColumns() // Load all columns in parallel - await Promise.all(columns.map((column) => loadColumnJobs(column.columnId, options))) + const outcomes = await Promise.all( + columns.map((column) => loadColumnJobs(column.columnId, options)), + ) + const succeeded = outcomes.every((outcome) => outcome) + if (!succeeded) { + error.value = 'Failed to load one or more Kanban columns' + return false + } notifyJobsLoaded() + return true } catch (err) { error.value = err instanceof Error ? err.message : 'Failed to load kanban columns' log('Error loading kanban columns:', err) + return false } finally { - isLoading.value = false - jobsStore.setLoadingKanban(false) + endLoadingOperation() + kanbanLoadOperationCount -= 1 + jobsStore.setLoadingKanban(kanbanLoadOperationCount > 0) } } // Revalidate specific columns (for optimistic updates) - const revalidateColumns = async (columnIds: string[]): Promise => { + const revalidateColumns = async (columnIds: string[]): Promise => { log(`Revalidating columns: ${columnIds.join(', ')}`) - await Promise.all(columnIds.map((columnId) => loadColumnJobs(columnId, { force: true }))) + const outcomes = await Promise.all( + columnIds.map((columnId) => loadColumnJobs(columnId, { force: true })), + ) + return outcomes.every((outcome) => outcome) + } + + const replaceLocalKanbanJob = (job: KanbanJob): void => { + jobsStore.setKanbanJob(job) + Object.values(columnStates).forEach((columnState) => { + if (!columnState.jobs.some((currentJob) => currentJob.id === job.id)) { + return + } + columnState.jobs = columnState.jobs.map((currentJob) => + currentJob.id === job.id ? job : currentJob, + ) + }) + if (filteredJobs.value.some((currentJob) => currentJob.id === job.id)) { + filteredJobs.value = sortJobsForKanbanDisplay( + filteredJobs.value.map((currentJob) => (currentJob.id === job.id ? job : currentJob)), + ) + } } + const removeLocalKanbanJob = (jobId: string): void => { + jobsStore.removeKanbanJob(jobId) + Object.values(columnStates).forEach((columnState) => { + if (!columnState.jobs.some((job) => job.id === jobId)) { + return + } + columnState.jobs = columnState.jobs.filter((job) => job.id !== jobId) + }) + filteredJobs.value = filteredJobs.value.filter((job) => job.id !== jobId) + } + + const handleKanbanFreshnessChange = async (previousVersion: string): Promise => { + const response = await jobService.getKanbanChanges(previousVersion) + if (response.full_refresh_required) { + jobsStore.clearKanbanColumnCache() + const reloaded = await loadAllColumns({ force: true }) + if (!reloaded) { + throw new Error('Failed to reload Kanban after unsafe incremental response') + } + await refreshActiveSearch() + return + } + + const columnsToRevalidate = new Set() + for (const changedJob of response.jobs) { + const previousJob = + jobsStore.getKanbanJobById(changedJob.id) ?? + filteredJobs.value.find((job) => job.id === changedJob.id) ?? + null + + replaceLocalKanbanJob(changedJob) + if (!previousJob) { + columnsToRevalidate.add(KanbanCategorizationService.getColumnForStatus(changedJob.status)) + continue + } + if ( + previousJob.status === changedJob.status && + previousJob.priority === changedJob.priority + ) { + continue + } + + columnsToRevalidate.add(KanbanCategorizationService.getColumnForStatus(previousJob.status)) + columnsToRevalidate.add(KanbanCategorizationService.getColumnForStatus(changedJob.status)) + } + + for (const removedJobId of response.removed_job_ids) { + const previousJob = + jobsStore.getKanbanJobById(removedJobId) ?? + filteredJobs.value.find((job) => job.id === removedJobId) ?? + null + removeLocalKanbanJob(removedJobId) + if (previousJob) { + columnsToRevalidate.add(KanbanCategorizationService.getColumnForStatus(previousJob.status)) + } + } + + if (columnsToRevalidate.size > 0) { + const revalidated = await revalidateColumns([...columnsToRevalidate]) + if (!revalidated) { + throw new Error('Failed to revalidate changed Kanban columns') + } + } + await refreshActiveSearch() + } + + const unsubscribeKanbanFreshness = dataFreshness.subscribe('kanban', handleKanbanFreshnessChange) + const unsubscribeKanbanRelatedFreshness = dataFreshness.subscribe('kanban_related', async () => { + const reloaded = await loadAllColumns({ force: true }) + if (!reloaded) { + throw new Error('Failed to reload Kanban related display data') + } + await refreshActiveSearch() + }) + onUnmounted(() => { + unsubscribeKanbanFreshness() + unsubscribeKanbanRelatedFreshness() + }) + const getColumnJobIds = (columnId: string): string[] => (columnStates[columnId]?.jobs ?? []).map((job) => job.id) @@ -419,8 +559,7 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { // Get jobs for a specific column with staff filtering const getJobsByStatus = computed(() => (columnId: string) => { - // Show filtered results when: we have results, there's a search query, OR we're loading a search - if (filteredJobs.value.length > 0 || searchQuery.value.trim() !== '' || isLoading.value) { + if (searchMode.value !== 'none') { // When searching, group filteredJobs by column const grouped: Record = {} filteredJobs.value.forEach((job) => { @@ -469,11 +608,7 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { // Whether search/filter is active const isSearchActive = computed(() => { - return ( - filteredJobs.value.length > 0 || - searchQuery.value.trim() !== '' || - activeStaffFilters.value.length > 0 - ) + return searchMode.value !== 'none' || activeStaffFilters.value.length > 0 }) const insertJobInColumn = ( @@ -916,13 +1051,21 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { } } - const performBackendSearch = async (query: string, requestId: number): Promise => { - if (requestId !== latestSearchRequestId || searchQuery.value.trim() !== query) { + const performBackendSearch = async ( + query: string, + requestId: number, + fallbackLocally: boolean, + ): Promise => { + if ( + requestId !== latestSearchRequestId || + searchMode.value !== 'quick' || + searchQuery.value.trim() !== query + ) { return } try { - isLoading.value = true + beginLoadingOperation() const searchFilters: AdvancedFilters = { ...DEFAULT_ADVANCED_FILTERS, @@ -930,7 +1073,11 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { } const response: AdvancedSearchResponse = await jobService.performAdvancedSearch(searchFilters) - if (requestId !== latestSearchRequestId || searchQuery.value.trim() !== query) { + if ( + requestId !== latestSearchRequestId || + searchMode.value !== 'quick' || + searchQuery.value.trim() !== query + ) { return } @@ -948,20 +1095,25 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { renderedColumnOrder: summarizeFilteredColumnOrder(filteredJobs.value), }) } catch (err) { - if (requestId !== latestSearchRequestId || searchQuery.value.trim() !== query) { + if ( + requestId !== latestSearchRequestId || + searchMode.value !== 'quick' || + searchQuery.value.trim() !== query + ) { return } log('Error performing search:', err) + if (!fallbackLocally) { + throw err + } filteredJobs.value = searchJobsLocally(getAllLoadedJobs(), query) } finally { - if (requestId === latestSearchRequestId) { - isLoading.value = false - } + endLoadingOperation() } } const debouncedBackendSearch = useDebounceFn((query: string, requestId: number) => { - return performBackendSearch(query, requestId) + return performBackendSearch(query, requestId, true) }, 300) // Search functionality - show immediate local substring matches, then @@ -972,11 +1124,12 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { const requestId = latestSearchRequestId if (!trimmedQuery) { + searchMode.value = 'none' filteredJobs.value = [] - isLoading.value = false return } + searchMode.value = 'quick' filteredJobs.value = searchJobsLocally(getAllLoadedJobs(), trimmedQuery) debouncedBackendSearch(trimmedQuery, requestId) @@ -987,22 +1140,24 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { ) } - // Advanced search - const handleAdvancedSearch = async (): Promise => { + const advancedFiltersForBackend = (): AdvancedFilters => + ({ + ...advancedFilters.value, + status: Array.isArray(advancedFilters.value.status) + ? advancedFilters.value.status.join(',') + : advancedFilters.value.status, + }) as unknown as AdvancedFilters + + const performAdvancedSearchRequest = async ( + filters: AdvancedFilters, + requestId: number, + ): Promise => { try { - isLoading.value = true - filteredJobs.value = [] - - // Convert array fields to comma-separated strings for backend - const backendFilters = { - ...advancedFilters.value, - status: Array.isArray(advancedFilters.value.status) - ? advancedFilters.value.status.join(',') - : advancedFilters.value.status, - } as unknown as AdvancedFilters - - const response: AdvancedSearchResponse = - await jobService.performAdvancedSearch(backendFilters) + beginLoadingOperation() + const response: AdvancedSearchResponse = await jobService.performAdvancedSearch(filters) + if (requestId !== latestSearchRequestId || searchMode.value !== 'advanced') { + return + } if (!response.jobs) { throw new Error( `Advanced search response missing jobs: ${response.error ?? 'no error given'}`, @@ -1010,22 +1165,66 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { } filteredJobs.value = response.jobs } catch (err) { - error.value = err instanceof Error ? err.message : 'Failed to perform advanced search' - log('Error performing advanced search:', err) - filteredJobs.value = [] + if (requestId !== latestSearchRequestId || searchMode.value !== 'advanced') { + return + } throw err } finally { - isLoading.value = false + endLoadingOperation() } } + // Advanced search + const handleAdvancedSearch = async (): Promise => { + latestSearchRequestId += 1 + const requestId = latestSearchRequestId + searchMode.value = 'advanced' + filteredJobs.value = [] + + try { + await performAdvancedSearchRequest(advancedFiltersForBackend(), requestId) + } catch (err) { + if (requestId === latestSearchRequestId && searchMode.value === 'advanced') { + error.value = err instanceof Error ? err.message : 'Failed to perform advanced search' + log('Error performing advanced search:', err) + filteredJobs.value = [] + } + throw err + } + } + + const refreshActiveSearch = async (): Promise => { + if (searchMode.value === 'none') { + return + } + + latestSearchRequestId += 1 + const requestId = latestSearchRequestId + if (searchMode.value === 'quick') { + const query = searchQuery.value.trim() + if (!query) { + searchMode.value = 'none' + filteredJobs.value = [] + return + } + await performBackendSearch(query, requestId, false) + return + } + + await performAdvancedSearchRequest(advancedFiltersForBackend(), requestId) + } + // Utility functions const clearFilters = (): void => { + latestSearchRequestId += 1 + searchMode.value = 'none' advancedFilters.value = { ...DEFAULT_ADVANCED_FILTERS } filteredJobs.value = [] } const backToKanban = (): void => { + latestSearchRequestId += 1 + searchMode.value = 'none' searchQuery.value = '' filteredJobs.value = [] const newQuery = { ...route.query } diff --git a/frontend/src/services/job.service.ts b/frontend/src/services/job.service.ts index 5420fcc92..c2ceca912 100644 --- a/frontend/src/services/job.service.ts +++ b/frontend/src/services/job.service.ts @@ -172,6 +172,7 @@ type JobFileRequest = z.infer type FetchAllJobsResponse = z.infer type FetchJobsResponse = z.infer type FetchJobsByColumnResponse = z.infer +type KanbanChangesResponse = z.infer type FetchStatusValuesResponse = z.infer type CompanyDefaults = z.infer type PaginatedCompleteJobList = z.infer @@ -199,6 +200,10 @@ export const jobService = { }) }, + getKanbanChanges(after: string): Promise { + return api.getKanbanChanges({ queries: { after } }) + }, + getStatusChoices(): Promise { return Promise.resolve({ success: true, diff --git a/frontend/src/stores/__tests__/jobs.test.ts b/frontend/src/stores/__tests__/jobs.test.ts index 2369cf7c1..7a962b863 100644 --- a/frontend/src/stores/__tests__/jobs.test.ts +++ b/frontend/src/stores/__tests__/jobs.test.ts @@ -2,6 +2,10 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { createPinia, setActivePinia } from 'pinia' import { useJobsStore } from '@/stores/jobs' +const { freshnessSubscribers } = vi.hoisted(() => ({ + freshnessSubscribers: new Map void | Promise>(), +})) + vi.mock('@/api/client', () => ({ api: {}, })) @@ -12,7 +16,10 @@ vi.mock('@/services/job.service', () => ({ vi.mock('@/composables/useDataFreshness', () => ({ dataFreshness: { - subscribe: vi.fn(), + subscribe: vi.fn((key: string, callback: () => void | Promise) => { + freshnessSubscribers.set(key, callback) + return vi.fn() + }), }, })) @@ -52,6 +59,7 @@ describe('jobs store kanban cache', () => { beforeEach(() => { setActivePinia(createPinia()) vi.clearAllMocks() + freshnessSubscribers.clear() }) it('normalizes column responses into jobs by id plus ordered column ids', async () => { @@ -96,6 +104,24 @@ describe('jobs store kanban cache', () => { expect(store.getKanbanColumnJobs('in_progress')?.[0]?.name).toBe('Updated') }) + it('clears the complete kanban cache when related display data changes', async () => { + const store = useJobsStore() + + await store.loadKanbanColumnWithCache('in_progress', async () => ({ + success: true, + jobs: [buildKanbanJob()], + total: 1, + filtered_count: 1, + has_more: false, + })) + + expect(freshnessSubscribers.has('kanban')).toBe(false) + await freshnessSubscribers.get('kanban_related')?.() + + expect(store.kanbanColumnCache).toEqual({}) + expect(store.kanbanJobs).toEqual({}) + }) + it('moves cached kanban job ids above or below a visible anchor', async () => { const store = useJobsStore() diff --git a/frontend/src/stores/jobs.ts b/frontend/src/stores/jobs.ts index d75b94a0f..8affb1941 100644 --- a/frontend/src/stores/jobs.ts +++ b/frontend/src/stores/jobs.ts @@ -52,7 +52,7 @@ export const useJobsStore = defineStore('jobs', () => { }, }) - dataFreshness.subscribe('kanban', () => { + dataFreshness.subscribe('kanban_related', () => { kanbanDatasetCache.invalidate() }) diff --git a/frontend/src/typed-router.d.ts b/frontend/src/typed-router.d.ts index 32e776607..b11d0a54e 100644 --- a/frontend/src/typed-router.d.ts +++ b/frontend/src/typed-router.d.ts @@ -20,9 +20,9 @@ import type { declare module 'vue-router' { interface TypesConfig { - ParamParsers: - | never + _ParamParsers: {} RouteNamedMap: import('vue-router/auto-routes').RouteNamedMap + _RouteFileInfoMap: import('vue-router/auto-routes')._RouteFileInfoMap } } @@ -329,240 +329,320 @@ declare module 'vue-router/auto-routes' { | '/[...path]' views: | never + pathParamNames: + | 'path' } 'src/pages/crm/calls.vue': { routes: | '/crm/calls' views: | never + pathParamNames: + | never } 'src/pages/crm/companies/(index).vue': { routes: | '/crm/companies/(index)' views: | never + pathParamNames: + | never } 'src/pages/crm/companies/[id].vue': { routes: | '/crm/companies/[id]' views: | never + pathParamNames: + | 'id' } 'src/pages/crm/people/(index).vue': { routes: | '/crm/people/(index)' views: | never + pathParamNames: + | never } 'src/pages/crm/people/[id].vue': { routes: | '/crm/people/[id]' views: | never + pathParamNames: + | 'id' } 'src/pages/jobs/[id]/(index).vue': { routes: | '/jobs/[id]/(index)' views: | never + pathParamNames: + | never } 'src/pages/jobs/[id]/workshop.vue': { routes: | '/jobs/[id]/workshop' views: | never + pathParamNames: + | never } 'src/pages/jobs/create.vue': { routes: | '/jobs/create' views: | never + pathParamNames: + | never } 'src/pages/kanban.vue': { routes: | '/kanban' views: | never + pathParamNames: + | never } 'src/pages/login.vue': { routes: | '/login' views: | never + pathParamNames: + | never } 'src/pages/purchasing/mappings.vue': { routes: | '/purchasing/mappings' views: | never + pathParamNames: + | never } 'src/pages/purchasing/po/(index).vue': { routes: | '/purchasing/po/(index)' views: | never + pathParamNames: + | never } 'src/pages/purchasing/po/[id].vue': { routes: | '/purchasing/po/[id]' views: | never + pathParamNames: + | 'id' } 'src/pages/purchasing/po/create.vue': { routes: | '/purchasing/po/create' views: | never + pathParamNames: + | never } 'src/pages/purchasing/po/create-from-quote.vue': { routes: | '/purchasing/po/create-from-quote' views: | never + pathParamNames: + | never } 'src/pages/purchasing/pricing.vue': { routes: | '/purchasing/pricing' views: | never + pathParamNames: + | never } 'src/pages/purchasing/stock.vue': { routes: | '/purchasing/stock' views: | never + pathParamNames: + | never } 'src/pages/quoting/chat.vue': { routes: | '/quoting/chat' views: | never + pathParamNames: + | never } 'src/pages/reports/data-quality/archived-jobs.vue': { routes: | '/reports/data-quality/archived-jobs' views: | never + pathParamNames: + | never } 'src/pages/reports/data-quality/duplicate-identities.vue': { routes: | '/reports/data-quality/duplicate-identities' views: | never + pathParamNames: + | never } 'src/pages/reports/data-quality/duplicate-phones.vue': { routes: | '/reports/data-quality/duplicate-phones' views: | never + pathParamNames: + | never } 'src/pages/reports/job-aging.vue': { routes: | '/reports/job-aging' views: | never + pathParamNames: + | never } 'src/pages/reports/job-movement.vue': { routes: | '/reports/job-movement' views: | never + pathParamNames: + | never } 'src/pages/reports/job-profitability.vue': { routes: | '/reports/job-profitability' views: | never + pathParamNames: + | never } 'src/pages/reports/kpi.vue': { routes: | '/reports/kpi' views: | never + pathParamNames: + | never } 'src/pages/reports/payroll-reconciliation.vue': { routes: | '/reports/payroll-reconciliation' views: | never + pathParamNames: + | never } 'src/pages/reports/profit-and-loss.vue': { routes: | '/reports/profit-and-loss' views: | never + pathParamNames: + | never } 'src/pages/reports/rdti-spend.vue': { routes: | '/reports/rdti-spend' views: | never + pathParamNames: + | never } 'src/pages/reports/sales-forecast.vue': { routes: | '/reports/sales-forecast' views: | never + pathParamNames: + | never } 'src/pages/reports/sales-pipeline.vue': { routes: | '/reports/sales-pipeline' views: | never + pathParamNames: + | never } 'src/pages/reports/staff-performance.vue': { routes: | '/reports/staff-performance' views: | never + pathParamNames: + | never } 'src/pages/reports/wip.vue': { routes: | '/reports/wip' views: | never + pathParamNames: + | never } 'src/pages/schedule.vue': { routes: | '/schedule' views: | never + pathParamNames: + | never } 'src/pages/session-check.vue': { routes: | '/session-check' views: | never + pathParamNames: + | never } 'src/pages/timesheets/daily.vue': { routes: | '/timesheets/daily' views: | never + pathParamNames: + | never } 'src/pages/timesheets/entry.vue': { routes: | '/timesheets/entry' views: | never + pathParamNames: + | never } 'src/pages/timesheets/my-time.vue': { routes: | '/timesheets/my-time' views: | never + pathParamNames: + | never } 'src/pages/timesheets/weekly.vue': { routes: | '/timesheets/weekly' views: | never + pathParamNames: + | never } 'src/pages/xero.vue': { routes: | '/xero' views: | never + pathParamNames: + | never } } From 9df6d46018d9d08a830af8bf47de8434be156543 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 14:47:53 +1200 Subject: [PATCH 10/39] fix: address kanban freshness review findings --- apps/job/models/job.py | 4 + apps/job/serializers/kanban_serializer.py | 2 +- apps/job/services/__init__.py | 2 - apps/job/services/job_rest_service.py | 28 +++---- apps/job/services/job_service.py | 2 +- apps/job/tests/test_job_rest_error_mapping.py | 7 +- apps/job/tests/test_job_rest_service.py | 2 +- apps/job/tests/test_kanban_changes.py | 30 ++++++++ apps/job/views/job_rest_views.py | 27 ++----- apps/purchasing/__init__.py | 2 - apps/purchasing/exceptions.py | 5 -- .../services/delivery_receipt_service.py | 2 +- .../services/purchasing_rest_service.py | 2 +- .../tests/test_purchase_order_etags.py | 3 +- .../purchasing/views/purchasing_rest_views.py | 35 +++------ apps/workflow/__init__.py | 2 + apps/workflow/exceptions.py | 4 + apps/workflow/services/__init__.py | 2 + apps/workflow/services/http_error_service.py | 33 +++++++++ .../workflow/tests/test_http_error_service.py | 73 +++++++++++++++++++ frontend/docs/jobview-etag-guide.md | 2 +- frontend/schema.yml | 2 +- frontend/src/api/generated/api.ts | 2 +- .../__tests__/useDataFreshness.test.ts | 65 ++++++++++++++--- .../__tests__/useOptimizedKanban.test.ts | 7 +- frontend/src/composables/useDataFreshness.ts | 11 ++- .../src/composables/useOptimizedKanban.ts | 23 +----- .../__tests__/job.service.search.test.ts | 39 ++++++++++ frontend/src/stores/jobs.ts | 1 - 29 files changed, 302 insertions(+), 117 deletions(-) delete mode 100644 apps/purchasing/exceptions.py create mode 100644 apps/workflow/services/http_error_service.py create mode 100644 apps/workflow/tests/test_http_error_service.py create mode 100644 frontend/src/services/__tests__/job.service.search.test.ts diff --git a/apps/job/models/job.py b/apps/job/models/job.py index 63155228b..66fed6ab1 100644 --- a/apps/job/models/job.py +++ b/apps/job/models/job.py @@ -77,6 +77,10 @@ def untracked_update(self, **kwargs): bookkeeping fields that are in UNTRACKED_FIELDS.""" return models.QuerySet.update(self, **kwargs) + def touch_updated_at(self, *, at: datetime) -> int: + """Advance only the aggregate freshness timestamp.""" + return models.QuerySet.update(self, updated_at=at) + JobManager = models.Manager.from_queryset(JobQuerySet) diff --git a/apps/job/serializers/kanban_serializer.py b/apps/job/serializers/kanban_serializer.py index 515858a32..a4edf863e 100644 --- a/apps/job/serializers/kanban_serializer.py +++ b/apps/job/serializers/kanban_serializer.py @@ -267,7 +267,7 @@ class FetchJobsByColumnResponseSerializer(serializers.Serializer): class KanbanChangesResponseSerializer(serializers.Serializer): """Serializer for incremental Kanban freshness reconciliation.""" - success = serializers.BooleanField(default=True) + success = serializers.BooleanField() jobs = KanbanColumnJobSerializer(many=True) removed_job_ids = serializers.ListField(child=serializers.UUIDField()) full_refresh_required = serializers.BooleanField() diff --git a/apps/job/services/__init__.py b/apps/job/services/__init__.py index 07b7c19aa..6eb43df58 100644 --- a/apps/job/services/__init__.py +++ b/apps/job/services/__init__.py @@ -36,7 +36,6 @@ DeltaValidationError, JobDeltaPayload, JobRestService, - PreconditionFailed, ) from .job_service import ( JobStaffService, @@ -128,7 +127,6 @@ "MonthEndService", "PaidFlagResult", "PaidFlagService", - "PreconditionFailed", "QuoteImportError", "QuoteImportResult", "QuoteModeController", diff --git a/apps/job/services/job_rest_service.py b/apps/job/services/job_rest_service.py index 7c55c25ee..4b9cabca6 100644 --- a/apps/job/services/job_rest_service.py +++ b/apps/job/services/job_rest_service.py @@ -16,7 +16,7 @@ from uuid import UUID, uuid4 from django.core.exceptions import ValidationError -from django.db import IntegrityError, models, transaction +from django.db import IntegrityError, transaction from django.shortcuts import get_object_or_404 from django.utils import timezone @@ -35,17 +35,14 @@ ) from apps.job.services.delta_checksum import compute_job_delta_checksum, normalise_value from apps.workflow.etag import if_match_satisfied +from apps.workflow.exceptions import PreconditionFailedError from apps.workflow.models import CompanyDefaults, XeroPayItem from apps.workflow.services.error_persistence import persist_app_error logger = logging.getLogger(__name__) -class PreconditionFailed(Exception): - """Raised when ETag precondition fails (HTTP 412).""" - - -class DeltaValidationError(PreconditionFailed): +class DeltaValidationError(PreconditionFailedError): """Raised when the delta payload fails checksum or before-state validation.""" def __init__( @@ -1057,7 +1054,7 @@ def update_job( logger.error( f"[JOB_UPDATE] ETag mismatch! Current: {current_etag}, Expected: {if_match}" ) - raise PreconditionFailed("ETag mismatch: resource has changed") + raise PreconditionFailedError("ETag mismatch: resource has changed") logger.debug("[JOB_UPDATE] ETag validation passed") # DEBUG: Log incoming data @@ -1133,7 +1130,7 @@ def update_job( job.save(staff=user, update_fields=["priority", "updated_at"]) result_job = job - # DeltaValidationError subclasses PreconditionFailed, so it must be + # DeltaValidationError subclasses PreconditionFailedError, so it must be # caught first or this arm is unreachable. except DeltaValidationError as exc: JobRestService._record_delta_rejection( @@ -1149,7 +1146,7 @@ def update_job( request_etag=delta_payload.etag or if_match or None, ) raise - except PreconditionFailed: + except PreconditionFailedError: if soft_fail_context: JobRestService._record_delta_rejection(**soft_fail_context) raise @@ -1228,7 +1225,7 @@ def undo_job_change( change_id=str(change_id), checksum=event.delta_checksum, ) - raise PreconditionFailed( + raise PreconditionFailedError( "Cannot undo change because the current job state no longer matches the original delta" ) @@ -1313,7 +1310,7 @@ def add_job_event( job = Job.objects.select_for_update().get(id=job_id) current_etag = generate_job_etag(job) if not if_match_satisfied(if_match, current_etag): - raise PreconditionFailed("ETag mismatch: resource has changed") + raise PreconditionFailedError("ETag mismatch: resource has changed") description_clean = description.strip() @@ -1354,9 +1351,8 @@ def add_job_event( f"Returning existing event: {event.id}" ) else: - models.QuerySet.update( - Job.objects.filter(pk=job.pk), - updated_at=timezone.now(), + Job.objects.filter(pk=job.pk).touch_updated_at( + at=timezone.now(), ) logger.info( @@ -1422,7 +1418,7 @@ def delete_job(job_id: UUID, user: Staff, if_match: str) -> Dict[str, Any]: job = get_object_or_404(Job.objects.select_for_update(), id=job_id) current_etag = generate_job_etag(job) if not if_match_satisfied(if_match, current_etag): - raise PreconditionFailed("ETag mismatch: resource has changed") + raise PreconditionFailedError("ETag mismatch: resource has changed") actual_cost_set = job.latest_actual if actual_cost_set and ( @@ -1452,7 +1448,7 @@ def accept_quote(job_id: UUID, user: Staff, if_match: str) -> Dict[str, Any]: current_etag = generate_job_etag(job) if not if_match_satisfied(if_match, current_etag): - raise PreconditionFailed("ETag mismatch: resource has changed") + raise PreconditionFailedError("ETag mismatch: resource has changed") if not job.latest_quote: raise ValueError("No quote found for this job") diff --git a/apps/job/services/job_service.py b/apps/job/services/job_service.py index 335ac1bf8..308ddba86 100644 --- a/apps/job/services/job_service.py +++ b/apps/job/services/job_service.py @@ -136,7 +136,7 @@ def recalculate_job_invoicing_state(job_id: str, staff) -> None: class JobStaffService: @staticmethod def _touch_job_for_assignment_change(job): - Job.objects.filter(id=job.id).update(updated_at=timezone.now()) + Job.objects.filter(id=job.id).touch_updated_at(at=timezone.now()) @staticmethod def assign_staff_to_job(job_id, staff_id): diff --git a/apps/job/tests/test_job_rest_error_mapping.py b/apps/job/tests/test_job_rest_error_mapping.py index 0a1f81fdf..7d5ff74e8 100644 --- a/apps/job/tests/test_job_rest_error_mapping.py +++ b/apps/job/tests/test_job_rest_error_mapping.py @@ -18,10 +18,11 @@ from rest_framework.exceptions import NotFound from apps.accounting.services.invoice_calculation import InvoiceCalculationError -from apps.job.services.job_rest_service import DeltaValidationError, PreconditionFailed +from apps.job.services.job_rest_service import DeltaValidationError from apps.job.views.job_rest_views import BaseJobRestView from apps.purchasing.services.allocation_service import AllocationDeletionError from apps.testing import BaseTestCase +from apps.workflow.exceptions import PreconditionFailedError from apps.workflow.models import AppError @@ -60,13 +61,13 @@ def test_value_error_subclasses_are_bad_requests_not_server_errors(self) -> None def test_precondition_failed_is_412(self) -> None: self.assert_maps_to( - PreconditionFailed("etag mismatch"), + PreconditionFailedError("etag mismatch"), status.HTTP_412_PRECONDITION_FAILED, "Precondition failed (ETag mismatch). Reload the job and retry.", ) def test_delta_validation_error_is_412_not_shadowed(self) -> None: - """DeltaValidationError subclasses PreconditionFailed; it must not + """DeltaValidationError subclasses PreconditionFailedError; it must not fall through to the generic ValueError or default arm.""" self.assert_maps_to( DeltaValidationError("checksum mismatch"), diff --git a/apps/job/tests/test_job_rest_service.py b/apps/job/tests/test_job_rest_service.py index a343d1b1f..2d76e840f 100644 --- a/apps/job/tests/test_job_rest_service.py +++ b/apps/job/tests/test_job_rest_service.py @@ -76,7 +76,7 @@ class JobRestServiceDeltaRejectionRecordingTests(BaseTestCase): def test_hard_checksum_mismatch_records_the_rejection(self) -> None: """A refused delta must leave a JobDeltaRejection explaining why. - ``DeltaValidationError`` subclasses ``PreconditionFailed``. If the + ``DeltaValidationError`` subclasses ``PreconditionFailedError``. If the broader handler is ordered first it swallows the specific one, and because ``soft_fail_context`` is still None that early in the update the rejection is dropped entirely — the only record of why a client's diff --git a/apps/job/tests/test_kanban_changes.py b/apps/job/tests/test_kanban_changes.py index 0c6a02ad0..3fbf45031 100644 --- a/apps/job/tests/test_kanban_changes.py +++ b/apps/job/tests/test_kanban_changes.py @@ -9,6 +9,7 @@ from apps.company.models import Company from apps.job.etag import generate_job_etag from apps.job.models import Job +from apps.job.serializers.kanban_serializer import KanbanChangesResponseSerializer from apps.testing import BaseAPITestCase from apps.workflow.models import AppError, XeroPayItem @@ -19,6 +20,7 @@ class KanbanCardPayload(TypedDict): class KanbanChangesPayload(TypedDict): + success: bool jobs: list[KanbanCardPayload] removed_job_ids: list[str] full_refresh_required: bool @@ -103,6 +105,22 @@ def test_reports_a_card_removed_when_it_moves_to_hidden_status(self) -> None: self.assertEqual(payload["jobs"], []) self.assertEqual(payload["removed_job_ids"], [str(self.first_job.id)]) + def test_returns_a_card_when_it_moves_to_the_archived_column(self) -> None: + version = self._kanban_version() + self.first_job.status = "archived" + self.first_job.save(staff=self.test_staff, update_fields=["status"]) + + response = self._changes_after(version) + + self.assertEqual(response.status_code, 200) + payload = response.json() + self.assertFalse(payload["full_refresh_required"]) + self.assertEqual( + [job["id"] for job in payload["jobs"]], + [str(self.first_job.id)], + ) + self.assertEqual(payload["removed_job_ids"], []) + def test_requires_full_refresh_when_job_count_changes(self) -> None: version = self._kanban_version() self._create_job("Newly created job", 9103) @@ -138,6 +156,18 @@ def test_rejects_missing_or_malformed_version(self) -> None: self.assertIn("error_id", malformed.json()["details"]) self.assertEqual(AppError.objects.count(), 1) + def test_success_is_required_by_the_response_contract(self) -> None: + serializer = KanbanChangesResponseSerializer( + data={ + "jobs": [], + "removed_job_ids": [], + "full_refresh_required": False, + } + ) + + self.assertFalse(serializer.is_valid()) + self.assertEqual(serializer.errors["success"][0].code, "required") + class ManualJobEventETagTests(BaseAPITestCase): def setUp(self) -> None: diff --git a/apps/job/views/job_rest_views.py b/apps/job/views/job_rest_views.py index c50ced358..1ffdcf751 100644 --- a/apps/job/views/job_rest_views.py +++ b/apps/job/views/job_rest_views.py @@ -14,7 +14,6 @@ from uuid import UUID from django.core.cache import cache -from django.db import IntegrityError from django.http import Http404, HttpRequest, JsonResponse from django.shortcuts import get_object_or_404 from django.utils.decorators import method_decorator @@ -22,7 +21,6 @@ from drf_spectacular.utils import OpenApiParameter, OpenApiTypes, extend_schema from rest_framework import status from rest_framework.decorators import api_view, permission_classes -from rest_framework.exceptions import NotFound from rest_framework.permissions import SAFE_METHODS, IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView @@ -58,11 +56,12 @@ from apps.job.services.job_rest_service import ( DeltaValidationError, JobRestService, - PreconditionFailed, ) from apps.workflow.etag import if_none_match_satisfied +from apps.workflow.exceptions import PreconditionFailedError from apps.workflow.models import CompanyDefaults from apps.workflow.services.error_persistence import persist_app_error +from apps.workflow.services.http_error_service import http_status_for_exception from apps.workflow.utils import parse_pagination_params logger = logging.getLogger(__name__) @@ -116,29 +115,17 @@ def handle_service_error(self, error: Exception) -> Response: error_message = str(error) - response_status: int - if isinstance(error, PreconditionFailed): - response_status = status.HTTP_412_PRECONDITION_FAILED + response_status = http_status_for_exception(error) + if isinstance(error, PreconditionFailedError): response_message = ( "Precondition failed (ETag mismatch). Reload the job and retry." ) - elif isinstance(error, (Http404, NotFound)): - response_status = status.HTTP_404_NOT_FOUND - response_message = error_message - elif isinstance(error, IntegrityError): - response_status = status.HTTP_409_CONFLICT - response_message = error_message - elif isinstance(error, PermissionError): - response_status = status.HTTP_403_FORBIDDEN - response_message = error_message - elif isinstance(error, ValueError): - response_status = status.HTTP_400_BAD_REQUEST - response_message = error_message else: - logger.error("Unhandled error: %s", error) - response_status = status.HTTP_500_INTERNAL_SERVER_ERROR response_message = error_message + if response_status == status.HTTP_500_INTERNAL_SERVER_ERROR: + logger.error("Unhandled error: %s", error) + error_serializer = JobRestErrorResponseSerializer( { "error": response_message, diff --git a/apps/purchasing/__init__.py b/apps/purchasing/__init__.py index 5dcad7a61..3de4dd4b3 100644 --- a/apps/purchasing/__init__.py +++ b/apps/purchasing/__init__.py @@ -1,7 +1,6 @@ # This file is autogenerated by update_init.py script from .apps import PurchasingConfig -from .exceptions import PreconditionFailedError # Conditional imports (only when Django is ready) try: @@ -90,7 +89,6 @@ "JobForPurchasingSerializer", "ParseStockItemTask", "ParseUnparsedStockItemsTask", - "PreconditionFailedError", "ProductMappingListResponseSerializer", "ProductMappingSerializer", "ProductMappingValidateResponseSerializer", diff --git a/apps/purchasing/exceptions.py b/apps/purchasing/exceptions.py deleted file mode 100644 index 0a76b0b6c..000000000 --- a/apps/purchasing/exceptions.py +++ /dev/null @@ -1,5 +0,0 @@ -class PreconditionFailedError(Exception): - """Raised when optimistic concurrency preconditions are not met.""" - - -__all__ = ["PreconditionFailedError"] diff --git a/apps/purchasing/services/delivery_receipt_service.py b/apps/purchasing/services/delivery_receipt_service.py index ed36f26a2..7a3268c84 100644 --- a/apps/purchasing/services/delivery_receipt_service.py +++ b/apps/purchasing/services/delivery_receipt_service.py @@ -10,13 +10,13 @@ from apps.job.models import CostLine, CostSet, Job from apps.purchasing.etag import generate_po_etag -from apps.purchasing.exceptions import PreconditionFailedError from apps.purchasing.models import PurchaseOrder, PurchaseOrderLine, Stock from apps.purchasing.tasks import ( enqueue_stock_metadata_parse, stock_metadata_parse_eligible, ) from apps.workflow.etag import if_match_satisfied +from apps.workflow.exceptions import PreconditionFailedError from apps.workflow.models.company_defaults import CompanyDefaults from apps.workflow.services.error_persistence import persist_app_error from apps.workflow.services.validation import to_decimal diff --git a/apps/purchasing/services/purchasing_rest_service.py b/apps/purchasing/services/purchasing_rest_service.py index 078c14dc8..1afb8183a 100644 --- a/apps/purchasing/services/purchasing_rest_service.py +++ b/apps/purchasing/services/purchasing_rest_service.py @@ -17,7 +17,6 @@ from apps.job.models.costing import CostLine from apps.job.models.job import Job from apps.purchasing.etag import generate_po_etag -from apps.purchasing.exceptions import PreconditionFailedError from apps.purchasing.models import PurchaseOrder, PurchaseOrderLine, Stock from apps.purchasing.services.delivery_receipt_service import ( _create_costline_from_allocation, @@ -28,6 +27,7 @@ stock_metadata_parse_eligible, ) from apps.workflow.etag import if_match_satisfied +from apps.workflow.exceptions import PreconditionFailedError from apps.workflow.models import CompanyDefaults logger = logging.getLogger(__name__) diff --git a/apps/purchasing/tests/test_purchase_order_etags.py b/apps/purchasing/tests/test_purchase_order_etags.py index 60d5af06a..8d5fffcf0 100644 --- a/apps/purchasing/tests/test_purchase_order_etags.py +++ b/apps/purchasing/tests/test_purchase_order_etags.py @@ -84,6 +84,7 @@ def test_delivery_receipt_rejects_a_stale_etag(self) -> None: def test_patch_rejects_a_weak_if_match_tag(self) -> None: current_etag = self._current_etag() + initial_reference = self.purchase_order.reference response = self.client.patch( self.detail_url, @@ -94,7 +95,7 @@ def test_patch_rejects_a_weak_if_match_tag(self) -> None: self.assertEqual(response.status_code, 412) self.purchase_order.refresh_from_db() - self.assertIsNone(self.purchase_order.reference) + self.assertEqual(self.purchase_order.reference, initial_reference) def test_etag_distinguishes_changes_within_one_millisecond(self) -> None: first_timestamp = self.purchase_order.updated_at diff --git a/apps/purchasing/views/purchasing_rest_views.py b/apps/purchasing/views/purchasing_rest_views.py index 694ed06ba..06f4c1776 100644 --- a/apps/purchasing/views/purchasing_rest_views.py +++ b/apps/purchasing/views/purchasing_rest_views.py @@ -67,18 +67,18 @@ create_purchase_order_pdf, ) from apps.purchasing.services.purchasing_rest_service import ( - PreconditionFailedError, PurchasingRestService, ) from apps.workflow.etag import if_none_match_satisfied +from apps.workflow.exceptions import PreconditionFailedError from apps.workflow.services.error_persistence import persist_app_error +from apps.workflow.services.http_error_service import http_status_for_exception logger = logging.getLogger(__name__) def _purchase_order_error_response( exc: Exception, - response_status: int, ) -> Response: """Persist and serialize an exception-derived PO error response.""" app_error = persist_app_error(exc) @@ -89,7 +89,7 @@ def _purchase_order_error_response( "details": {"error_id": app_error.id}, } ) - return Response(serializer.data, status=response_status) + return Response(serializer.data, status=http_status_for_exception(exc)) class PurchaseOrderETagMixin: @@ -524,26 +524,17 @@ def patch(self, request, po_id): logger.warning( "ETag mismatch updating purchase order %s: %s", po_id, str(exc) ) - return _purchase_order_error_response( - exc, - status.HTTP_412_PRECONDITION_FAILED, - ) + return _purchase_order_error_response(exc) except ValidationError as exc: logger.warning( "Validation error updating purchase order %s: %s", po_id, str(exc) ) - return _purchase_order_error_response( - exc, - status.HTTP_400_BAD_REQUEST, - ) + return _purchase_order_error_response(exc) except Exception as exc: logger.exception("Error updating purchase order %s", po_id) - return _purchase_order_error_response( - exc, - status.HTTP_500_INTERNAL_SERVER_ERROR, - ) + return _purchase_order_error_response(exc) class DeliveryReceiptRestView(PurchaseOrderETagMixin, APIView): @@ -605,23 +596,17 @@ def post(self, request): purchase_order_id, str(exc), ) - return _purchase_order_error_response( - exc, - status.HTTP_412_PRECONDITION_FAILED, - ) + return _purchase_order_error_response(exc) except DeliveryReceiptValidationError as exc: - return _purchase_order_error_response(exc, status.HTTP_400_BAD_REQUEST) + return _purchase_order_error_response(exc) except PurchaseOrder.DoesNotExist as exc: - return _purchase_order_error_response(exc, status.HTTP_404_NOT_FOUND) + return _purchase_order_error_response(exc) except Exception as exc: logger.exception("Error processing delivery receipt") - return _purchase_order_error_response( - exc, - status.HTTP_500_INTERNAL_SERVER_ERROR, - ) + return _purchase_order_error_response(exc) class PurchaseOrderAllocationsAPIView(APIView): diff --git a/apps/workflow/__init__.py b/apps/workflow/__init__.py index da63fa19a..37554aa05 100644 --- a/apps/workflow/__init__.py +++ b/apps/workflow/__init__.py @@ -4,6 +4,7 @@ from .enums import AIProviderTypes, NotebookLmRestriction from .exceptions import ( NoValidXeroTokenError, + PreconditionFailedError, XeroQuotaFloorReached, XeroSyncAlreadyRunningError, XeroValidationError, @@ -134,6 +135,7 @@ "NotebookLmRestriction", "NullUnsetModelSerializer", "PasswordStrengthMiddleware", + "PreconditionFailedError", "SearchTelemetryClickRequestSerializer", "SearchTelemetryClickResponseSerializer", "ServiceAPIKeyAuthentication", diff --git a/apps/workflow/exceptions.py b/apps/workflow/exceptions.py index d081ec4c2..ec2648aa0 100644 --- a/apps/workflow/exceptions.py +++ b/apps/workflow/exceptions.py @@ -1,6 +1,10 @@ from typing import List, Optional +class PreconditionFailedError(Exception): + """Raised when an optimistic-concurrency precondition is not met.""" + + class XeroValidationError(Exception): """Exception raised when a Xero object is missing required fields. diff --git a/apps/workflow/services/__init__.py b/apps/workflow/services/__init__.py index 653b969c4..cae4c57b9 100644 --- a/apps/workflow/services/__init__.py +++ b/apps/workflow/services/__init__.py @@ -34,6 +34,7 @@ persist_app_error, persist_xero_error, ) + from .http_error_service import http_status_for_exception from .instance_onboarding import finalize_instance_onboarding from .llm_service import LLMService, quick_completion, quick_json_completion from .request import get_client_ip @@ -75,6 +76,7 @@ "finalize_instance_onboarding", "get_client_ip", "get_closed_e2e_windows", + "http_status_for_exception", "is_test_company_name", "list_app_errors", "list_grouped_app_errors", diff --git a/apps/workflow/services/http_error_service.py b/apps/workflow/services/http_error_service.py new file mode 100644 index 000000000..43e95649d --- /dev/null +++ b/apps/workflow/services/http_error_service.py @@ -0,0 +1,33 @@ +"""Map boundary exceptions to their HTTP status codes.""" + +from django.core.exceptions import ( + ObjectDoesNotExist, +) +from django.core.exceptions import PermissionDenied as DjangoPermissionDenied +from django.core.exceptions import ValidationError as DjangoValidationError +from django.db import IntegrityError +from django.http import Http404 +from rest_framework import status +from rest_framework.exceptions import NotFound +from rest_framework.exceptions import PermissionDenied as DRFPermissionDenied +from rest_framework.exceptions import ValidationError as DRFValidationError + +from apps.workflow.exceptions import PreconditionFailedError + + +def http_status_for_exception(error: Exception) -> int: + """Return the status that represents ``error`` at an HTTP boundary.""" + if isinstance(error, PreconditionFailedError): + return status.HTTP_412_PRECONDITION_FAILED + if isinstance(error, (Http404, NotFound, ObjectDoesNotExist)): + return status.HTTP_404_NOT_FOUND + if isinstance(error, IntegrityError): + return status.HTTP_409_CONFLICT + if isinstance( + error, + (PermissionError, DjangoPermissionDenied, DRFPermissionDenied), + ): + return status.HTTP_403_FORBIDDEN + if isinstance(error, (ValueError, DjangoValidationError, DRFValidationError)): + return status.HTTP_400_BAD_REQUEST + return status.HTTP_500_INTERNAL_SERVER_ERROR diff --git a/apps/workflow/tests/test_http_error_service.py b/apps/workflow/tests/test_http_error_service.py new file mode 100644 index 000000000..4df8ddc04 --- /dev/null +++ b/apps/workflow/tests/test_http_error_service.py @@ -0,0 +1,73 @@ +"""HTTP status mapping follows exception semantics across API boundaries.""" + +from django.core.exceptions import ( + ObjectDoesNotExist, +) +from django.core.exceptions import PermissionDenied as DjangoPermissionDenied +from django.core.exceptions import ValidationError as DjangoValidationError +from django.db import IntegrityError +from django.http import Http404 +from rest_framework import status +from rest_framework.exceptions import NotFound +from rest_framework.exceptions import PermissionDenied as DRFPermissionDenied +from rest_framework.exceptions import ValidationError as DRFValidationError +from rest_framework.test import APISimpleTestCase + +from apps.workflow.exceptions import PreconditionFailedError +from apps.workflow.services.http_error_service import http_status_for_exception + + +class HttpStatusForExceptionTests(APISimpleTestCase): + def test_maps_precondition_failure_to_412(self) -> None: + self.assertEqual( + http_status_for_exception(PreconditionFailedError("stale")), + status.HTTP_412_PRECONDITION_FAILED, + ) + + def test_maps_not_found_variants_to_404(self) -> None: + for error in ( + Http404("missing"), + NotFound("missing"), + ObjectDoesNotExist("missing"), + ): + with self.subTest(error=type(error).__name__): + self.assertEqual( + http_status_for_exception(error), + status.HTTP_404_NOT_FOUND, + ) + + def test_maps_integrity_failure_to_409(self) -> None: + self.assertEqual( + http_status_for_exception(IntegrityError("conflict")), + status.HTTP_409_CONFLICT, + ) + + def test_maps_permission_variants_to_403(self) -> None: + for error in ( + PermissionError("denied"), + DjangoPermissionDenied("denied"), + DRFPermissionDenied("denied"), + ): + with self.subTest(error=type(error).__name__): + self.assertEqual( + http_status_for_exception(error), + status.HTTP_403_FORBIDDEN, + ) + + def test_maps_validation_variants_to_400(self) -> None: + for error in ( + ValueError("invalid"), + DjangoValidationError("invalid"), + DRFValidationError("invalid"), + ): + with self.subTest(error=type(error).__name__): + self.assertEqual( + http_status_for_exception(error), + status.HTTP_400_BAD_REQUEST, + ) + + def test_maps_unknown_failure_to_500(self) -> None: + self.assertEqual( + http_status_for_exception(RuntimeError("unexpected")), + status.HTTP_500_INTERNAL_SERVER_ERROR, + ) diff --git a/frontend/docs/jobview-etag-guide.md b/frontend/docs/jobview-etag-guide.md index 4a7e903d7..49f14415b 100644 --- a/frontend/docs/jobview-etag-guide.md +++ b/frontend/docs/jobview-etag-guide.md @@ -151,7 +151,7 @@ Testing checklist Change log - ETag enforcement and conditional GET added in views and services; see references above. -- 412 PreconditionFailed mapped in Base view; see BaseJobRestView.handle_service_error(). +- 412 PreconditionFailedError mapped in Base view; see BaseJobRestView.handle_service_error(). - Additional defensive checks in service prevent a person from leaking across unrelated companies after an update. --- diff --git a/frontend/schema.yml b/frontend/schema.yml index 432aca77e..087dfb262 100644 --- a/frontend/schema.yml +++ b/frontend/schema.yml @@ -16049,7 +16049,6 @@ components: properties: success: type: boolean - default: true jobs: type: array items: @@ -16067,6 +16066,7 @@ components: - full_refresh_required - jobs - removed_job_ids + - success KanbanColumnJob: type: object description: |- diff --git a/frontend/src/api/generated/api.ts b/frontend/src/api/generated/api.ts index 3bc51c047..91c76659b 100644 --- a/frontend/src/api/generated/api.ts +++ b/frontend/src/api/generated/api.ts @@ -2192,7 +2192,7 @@ const FetchJobsResponse = z }) .partial() const KanbanChangesResponse = z.object({ - success: z.boolean().optional().default(true), + success: z.boolean(), jobs: z.array(KanbanColumnJob), removed_job_ids: z.array(z.string().uuid()), full_refresh_required: z.boolean(), diff --git a/frontend/src/composables/__tests__/useDataFreshness.test.ts b/frontend/src/composables/__tests__/useDataFreshness.test.ts index 923b18aec..a6f70a9df 100644 --- a/frontend/src/composables/__tests__/useDataFreshness.test.ts +++ b/frontend/src/composables/__tests__/useDataFreshness.test.ts @@ -31,21 +31,68 @@ describe('useDataFreshness', () => { expect(onStale).toHaveBeenCalledWith('version-1', 'version-2') }) - it('retries a version change when its subscriber fails', async () => { + it('does not let a stale unsubscribe remove a newer subscriber bucket', async () => { + const firstSubscriber = vi.fn() + const unsubscribeFirst = dataFreshness.subscribe('kanban', firstSubscriber) + retrieveDataVersions.mockResolvedValueOnce({ kanban: 'version-1' }) + await dataFreshness.checkFreshness() + + unsubscribeFirst() + const newerSubscriber = vi.fn() + dataFreshness.subscribe('kanban', newerSubscriber) + unsubscribeFirst() + retrieveDataVersions.mockResolvedValueOnce({ kanban: 'version-2' }) + + await dataFreshness.checkFreshness() + + expect(newerSubscriber).toHaveBeenCalledWith('version-1', 'version-2') + }) + + it('runs every callback, surfaces the original failure, and retries only its dataset', async () => { const failure = new Error('incremental refresh failed') - const onStale = vi.fn().mockRejectedValueOnce(failure).mockResolvedValueOnce(undefined) - const consoleError = vi.spyOn(console, 'error').mockImplementation(() => undefined) - dataFreshness.subscribe('kanban', onStale) + const failingKanbanSubscriber = vi + .fn() + .mockRejectedValueOnce(failure) + .mockResolvedValueOnce(undefined) + const successfulKanbanSubscriber = vi.fn() + const stockSubscriber = vi.fn() + dataFreshness.subscribe('kanban', failingKanbanSubscriber) + dataFreshness.subscribe('kanban', successfulKanbanSubscriber) + dataFreshness.subscribe('stock', stockSubscriber) retrieveDataVersions - .mockResolvedValueOnce({ kanban: 'version-1' }) - .mockResolvedValue({ kanban: 'version-2' }) + .mockResolvedValueOnce({ kanban: 'kanban-1', stock: 'stock-1' }) + .mockResolvedValue({ kanban: 'kanban-2', stock: 'stock-2' }) await dataFreshness.checkFreshness() + await expect(dataFreshness.checkFreshness()).rejects.toBe(failure) await dataFreshness.checkFreshness() + + expect(failingKanbanSubscriber).toHaveBeenCalledTimes(2) + expect(successfulKanbanSubscriber).toHaveBeenCalledTimes(2) + expect(successfulKanbanSubscriber).toHaveBeenNthCalledWith(2, 'kanban-1', 'kanban-2') + expect(stockSubscriber).toHaveBeenCalledOnce() + expect(stockSubscriber).toHaveBeenCalledWith('stock-1', 'stock-2') + }) + + it('aggregates multiple callback failures after every callback runs', async () => { + const firstFailure = new Error('first failure') + const secondFailure = new Error('second failure') + const firstSubscriber = vi.fn().mockRejectedValue(firstFailure) + const secondSubscriber = vi.fn().mockRejectedValue(secondFailure) + dataFreshness.subscribe('kanban', firstSubscriber) + dataFreshness.subscribe('kanban', secondSubscriber) + retrieveDataVersions + .mockResolvedValueOnce({ kanban: 'version-1' }) + .mockResolvedValueOnce({ kanban: 'version-2' }) + await dataFreshness.checkFreshness() + const result = dataFreshness.checkFreshness() - expect(onStale).toHaveBeenCalledTimes(2) - expect(consoleError).toHaveBeenCalled() - consoleError.mockRestore() + await expect(result).rejects.toBeInstanceOf(AggregateError) + await expect(result).rejects.toMatchObject({ + errors: [firstFailure, secondFailure], + }) + expect(firstSubscriber).toHaveBeenCalledOnce() + expect(secondSubscriber).toHaveBeenCalledOnce() }) }) diff --git a/frontend/src/composables/__tests__/useOptimizedKanban.test.ts b/frontend/src/composables/__tests__/useOptimizedKanban.test.ts index a701c62ff..9645e8035 100644 --- a/frontend/src/composables/__tests__/useOptimizedKanban.test.ts +++ b/frontend/src/composables/__tests__/useOptimizedKanban.test.ts @@ -77,7 +77,6 @@ vi.mock('@/services/job.service', () => ({ vi.mock('@/stores/jobs', () => ({ useJobsStore: () => ({ - kanbanCacheGeneration: 0, getKanbanColumnCache: (columnId: string) => kanbanColumnCache.get(columnId) ?? null, getKanbanColumnJobs: (columnId: string) => { const cached = kanbanColumnCache.get(columnId) as { jobIds?: string[] } | undefined @@ -449,6 +448,7 @@ describe('useOptimizedKanban search reconciliation', () => { const kanban = await mountHarness() kanban.advancedFilters.value.name = 'Advanced' + kanban.advancedFilters.value.status = ['draft', 'approved'] await kanban.handleAdvancedSearch() expect(kanban.isSearchActive.value).toBe(true) @@ -463,7 +463,10 @@ describe('useOptimizedKanban search reconciliation', () => { expect(performAdvancedSearch).toHaveBeenCalledTimes(4) expect(performAdvancedSearch).toHaveBeenLastCalledWith( - expect.objectContaining({ name: 'Advanced' }), + expect.objectContaining({ + name: 'Advanced', + status: ['draft', 'approved'], + }), ) expect(kanban.isSearchActive.value).toBe(true) expect(kanban.getJobsByStatus.value('in_progress')).toEqual([]) diff --git a/frontend/src/composables/useDataFreshness.ts b/frontend/src/composables/useDataFreshness.ts index 3d0474c95..a8afb017b 100644 --- a/frontend/src/composables/useDataFreshness.ts +++ b/frontend/src/composables/useDataFreshness.ts @@ -20,7 +20,7 @@ function subscribe(key: string, onStale: StaleCallback): () => void { bucket.add(onStale) return () => { bucket?.delete(onStale) - if (bucket?.size === 0) { + if (bucket && bucket.size === 0 && subscribers.get(key) === bucket) { subscribers.delete(key) } } @@ -36,6 +36,7 @@ async function checkFreshness(): Promise { if (inFlight) return inFlight inFlight = (async () => { try { + const callbackErrors: unknown[] = [] const fresh = (await api.data_versions_retrieve()) as Record for (const [key, version] of Object.entries(fresh)) { const previous = knownVersions.get(key) @@ -52,13 +53,19 @@ async function checkFreshness(): Promise { await cb(previous, version) } catch (err) { callbacksSucceeded = false - console.error(`useDataFreshness: stale callback for "${key}" threw`, err) + callbackErrors.push(err) } } if (callbacksSucceeded) { knownVersions.set(key, version) } } + if (callbackErrors.length === 1) { + throw callbackErrors[0] + } + if (callbackErrors.length > 1) { + throw new AggregateError(callbackErrors, 'Multiple data freshness subscribers failed') + } } finally { inFlight = null } diff --git a/frontend/src/composables/useOptimizedKanban.ts b/frontend/src/composables/useOptimizedKanban.ts index af396d897..d0f8e9a72 100644 --- a/frontend/src/composables/useOptimizedKanban.ts +++ b/frontend/src/composables/useOptimizedKanban.ts @@ -69,7 +69,6 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { let latestSearchRequestId = 0 let loadingOperationCount = 0 let kanbanLoadOperationCount = 0 - let initialized = false let mounted = false let jobsLoadedCallbackPending = false let initialLoadPromise: Promise | null = null @@ -1140,14 +1139,6 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { ) } - const advancedFiltersForBackend = (): AdvancedFilters => - ({ - ...advancedFilters.value, - status: Array.isArray(advancedFilters.value.status) - ? advancedFilters.value.status.join(',') - : advancedFilters.value.status, - }) as unknown as AdvancedFilters - const performAdvancedSearchRequest = async ( filters: AdvancedFilters, requestId: number, @@ -1182,7 +1173,7 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { filteredJobs.value = [] try { - await performAdvancedSearchRequest(advancedFiltersForBackend(), requestId) + await performAdvancedSearchRequest(advancedFilters.value, requestId) } catch (err) { if (requestId === latestSearchRequestId && searchMode.value === 'advanced') { error.value = err instanceof Error ? err.message : 'Failed to perform advanced search' @@ -1211,7 +1202,7 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { return } - await performAdvancedSearchRequest(advancedFiltersForBackend(), requestId) + await performAdvancedSearchRequest(advancedFilters.value, requestId) } // Utility functions @@ -1277,14 +1268,6 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { activeStaffFilters.value = staffIds } - watch( - () => jobsStore.kanbanCacheGeneration, - async (newGeneration, oldGeneration) => { - if (!initialized || newGeneration === oldGeneration) return - await loadAllColumns({ force: true }) - }, - ) - const startInitialKanbanLoad = (): Promise => { if (initialLoadPromise) { return initialLoadPromise @@ -1300,11 +1283,9 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { if (hydratedFromCache) { notifyJobsLoaded() await loadStatusChoices() - initialized = true checkFreshnessInBackground() } else { await Promise.all([loadAllColumns(), loadStatusChoices()]) - initialized = true checkFreshnessInBackground() } diff --git a/frontend/src/services/__tests__/job.service.search.test.ts b/frontend/src/services/__tests__/job.service.search.test.ts new file mode 100644 index 000000000..a99256039 --- /dev/null +++ b/frontend/src/services/__tests__/job.service.search.test.ts @@ -0,0 +1,39 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { DEFAULT_ADVANCED_FILTERS } from '@/constants/advanced-filters' + +const { advancedSearch } = vi.hoisted(() => ({ + advancedSearch: vi.fn(), +})) + +vi.mock('@/api/client', () => ({ + api: { + job_jobs_advanced_search_retrieve: advancedSearch, + }, +})) + +import { jobService } from '@/services/job.service' + +describe('jobService advanced search', () => { + beforeEach(() => { + vi.clearAllMocks() + advancedSearch.mockResolvedValue({ jobs: [] }) + }) + + it('normalizes status arrays at the API boundary', async () => { + await jobService.performAdvancedSearch({ + ...DEFAULT_ADVANCED_FILTERS, + status: ['draft', 'approved'], + }) + await jobService.performAdvancedSearch({ + ...DEFAULT_ADVANCED_FILTERS, + status: [], + }) + + expect(advancedSearch).toHaveBeenNthCalledWith(1, { + queries: expect.objectContaining({ status: 'draft,approved' }), + }) + expect(advancedSearch).toHaveBeenNthCalledWith(2, { + queries: expect.objectContaining({ status: '' }), + }) + }) +}) diff --git a/frontend/src/stores/jobs.ts b/frontend/src/stores/jobs.ts index 8affb1941..5435678bd 100644 --- a/frontend/src/stores/jobs.ts +++ b/frontend/src/stores/jobs.ts @@ -613,7 +613,6 @@ export const useJobsStore = defineStore('jobs', () => { currentContext, allKanbanJobs, - kanbanCacheGeneration: computed(() => kanbanDatasetCache.generation.value), getJobById, getKanbanJobById, getHeaderById, From 354eb9cb5e6bf20fa0af29fae03e47e63be087e6 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 14:50:40 +1200 Subject: [PATCH 11/39] chore: shrink mypy baseline --- mypy-baseline.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index d3d71a813..4239298a4 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -319,7 +319,6 @@ apps/job/services/job_service.py:0: error: Function is missing a type annotation apps/job/services/job_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/services/job_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/job_service.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/services/job_service.py:0: error: Call to untyped function "_touch_job_for_assignment_change" of "JobStaffService" in typed context [no-untyped-call] apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -4005,7 +4004,6 @@ apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if funct apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Module "apps.purchasing.services.purchasing_rest_service" does not explicitly export attribute "PreconditionFailedError" [attr-defined] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] From b977de5547973b0f0874d619daf8c434b836752f Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 15:16:57 +1200 Subject: [PATCH 12/39] fix: preserve strong resource versions through gzip --- apps/workflow/__init__.py | 2 + apps/workflow/middleware.py | 21 +++++++++ .../tests/test_resource_version_middleware.py | 47 +++++++++++++++++++ docketworks/settings.py | 2 + .../__tests__/client.resourceVersion.test.ts | 21 +++++++++ frontend/src/api/client.ts | 34 +++++++++++--- 6 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 apps/workflow/tests/test_resource_version_middleware.py create mode 100644 frontend/src/api/__tests__/client.resourceVersion.test.ts diff --git a/apps/workflow/__init__.py b/apps/workflow/__init__.py index 37554aa05..066fa7884 100644 --- a/apps/workflow/__init__.py +++ b/apps/workflow/__init__.py @@ -35,6 +35,7 @@ FrontendRedirectMiddleware, LoginRequiredMiddleware, PasswordStrengthMiddleware, + ResourceVersionMiddleware, ) from .permissions import F from .search_telemetry_serializers import ( @@ -136,6 +137,7 @@ "NullUnsetModelSerializer", "PasswordStrengthMiddleware", "PreconditionFailedError", + "ResourceVersionMiddleware", "SearchTelemetryClickRequestSerializer", "SearchTelemetryClickResponseSerializer", "ServiceAPIKeyAuthentication", diff --git a/apps/workflow/middleware.py b/apps/workflow/middleware.py index 9bffbf0de..c72f9dcad 100644 --- a/apps/workflow/middleware.py +++ b/apps/workflow/middleware.py @@ -17,6 +17,27 @@ access_logger = logging.getLogger("access") +class ResourceVersionMiddleware: + """Preserve strong OCC tokens when gzip weakens representation ETags.""" + + _RESOURCE_ETAG_PREFIXES = ('"job:', '"po:') + + def __init__( + self, + get_response: Callable[[HttpRequest], HttpResponse], + ) -> None: + self.get_response = get_response + + def __call__(self, request: HttpRequest) -> HttpResponse: + response = self.get_response(request) + etag = response.headers.get("ETag") + if etag is None or not etag.startswith(self._RESOURCE_ETAG_PREFIXES): + return response + + response.headers["X-Resource-Version"] = etag + return response + + class DisallowedHostMiddleware: """ Middleware to catch DisallowedHost exceptions and return a clean 400 response. diff --git a/apps/workflow/tests/test_resource_version_middleware.py b/apps/workflow/tests/test_resource_version_middleware.py new file mode 100644 index 000000000..ed6aa6240 --- /dev/null +++ b/apps/workflow/tests/test_resource_version_middleware.py @@ -0,0 +1,47 @@ +"""OCC state tokens remain strong when response representations are gzipped.""" + +from django.http import HttpRequest, HttpResponse +from django.middleware.gzip import GZipMiddleware +from django.test import RequestFactory, SimpleTestCase + +from apps.workflow.middleware import ResourceVersionMiddleware + + +class ResourceVersionMiddlewareTests(SimpleTestCase): + def setUp(self) -> None: + self.request = RequestFactory().get("/", HTTP_ACCEPT_ENCODING="gzip") + + @staticmethod + def _response(etag: str) -> HttpResponse: + response = HttpResponse("compressible response " * 100) + response.headers["ETag"] = etag + return response + + def _process(self, etag: str) -> HttpResponse: + def view(_request: HttpRequest) -> HttpResponse: + return self._response(etag) + + preserve_version = ResourceVersionMiddleware(view) + gzip_response = GZipMiddleware(preserve_version) + return gzip_response(self.request) + + def test_preserves_job_and_po_versions_before_gzip_weakens_etag(self) -> None: + for strong_etag in ( + '"job:00000000-0000-0000-0000-000000000000:version"', + '"po:00000000-0000-0000-0000-000000000000:version"', + ): + with self.subTest(etag=strong_etag): + response = self._process(strong_etag) + + self.assertEqual(response.headers["Content-Encoding"], "gzip") + self.assertEqual(response.headers["ETag"], f"W/{strong_etag}") + self.assertEqual( + response.headers["X-Resource-Version"], + strong_etag, + ) + + def test_does_not_publish_unrelated_etag_as_a_resource_version(self) -> None: + response = self._process('"static-content-digest"') + + self.assertEqual(response.headers["ETag"], 'W/"static-content-digest"') + self.assertNotIn("X-Resource-Version", response.headers) diff --git a/docketworks/settings.py b/docketworks/settings.py index 4804c4d3e..16bf3a454 100644 --- a/docketworks/settings.py +++ b/docketworks/settings.py @@ -202,6 +202,8 @@ def validate_required_settings() -> None: "django.middleware.security.SecurityMiddleware", "apps.workflow.middleware.DisallowedHostMiddleware", "django.middleware.gzip.GZipMiddleware", + # Runs on the response before the outer gzip middleware weakens ETag. + "apps.workflow.middleware.ResourceVersionMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", diff --git a/frontend/src/api/__tests__/client.resourceVersion.test.ts b/frontend/src/api/__tests__/client.resourceVersion.test.ts new file mode 100644 index 000000000..fec41196b --- /dev/null +++ b/frontend/src/api/__tests__/client.resourceVersion.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'vitest' +import { strongResourceVersion } from '@/api/client' + +describe('strongResourceVersion', () => { + it('prefers the strong resource-version header over a weak response ETag', () => { + expect( + strongResourceVersion({ + 'x-resource-version': '"job:123:strong"', + etag: 'W/"compressed"', + }), + ).toBe('"job:123:strong"') + }) + + it('falls back to a strong ETag', () => { + expect(strongResourceVersion({ etag: '"po:456:strong"' })).toBe('"po:456:strong"') + }) + + it('ignores a weak-only ETag', () => { + expect(strongResourceVersion({ etag: 'W/"compressed"' })).toBeNull() + }) +}) diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 6d7ff16e7..acaa36d89 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -19,6 +19,26 @@ import { getSessionReplayId } from '@/services/sessionReplayState' const log = debug('api:client') +type ResourceVersionHeaders = { + 'x-resource-version'?: unknown + etag?: unknown +} + +function strongHeaderValue(value: unknown): string | null { + if (typeof value !== 'string') { + return null + } + const normalized = value.trim() + if (!normalized || /^W\//i.test(normalized)) { + return null + } + return normalized +} + +export function strongResourceVersion(headers: ResourceVersionHeaders): string | null { + return strongHeaderValue(headers['x-resource-version']) ?? strongHeaderValue(headers.etag) ?? null +} + // Global registry for ETag management to avoid circular imports let etagManager: { getETag: (jobId: string) => string | null @@ -158,22 +178,22 @@ axios.interceptors.response.use( (response) => { // Capture ETag from job endpoint responses const url = response.config.url || '' - const etag = response.headers['etag'] + const resourceVersion = strongResourceVersion(response.headers) - if (etag && isJobEndpoint(url)) { + if (resourceVersion && isJobEndpoint(url)) { const jobId = extractJobId(url) if (jobId && etagManager) { - etagManager.setETag(jobId, etag) - log(`Captured ETag for ${url}:`, etag) + etagManager.setETag(jobId, resourceVersion) + log(`Captured resource version for ${url}:`, resourceVersion) } } // Capture ETag from PO endpoint responses - if (etag && isPoEndpoint(url)) { + if (resourceVersion && isPoEndpoint(url)) { const poId = extractPoId(url) if (poId && poEtagManager) { - poEtagManager.setETag(poId, etag) - log(`Captured ETag for ${url}:`, etag) + poEtagManager.setETag(poId, resourceVersion) + log(`Captured resource version for ${url}:`, resourceVersion) } } From e30882835b9f66e8552bdf90aaedd8d7befa92db Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 15:19:09 +1200 Subject: [PATCH 13/39] test: narrow gzip middleware response --- apps/workflow/tests/test_resource_version_middleware.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/workflow/tests/test_resource_version_middleware.py b/apps/workflow/tests/test_resource_version_middleware.py index ed6aa6240..057ce9662 100644 --- a/apps/workflow/tests/test_resource_version_middleware.py +++ b/apps/workflow/tests/test_resource_version_middleware.py @@ -23,7 +23,10 @@ def view(_request: HttpRequest) -> HttpResponse: preserve_version = ResourceVersionMiddleware(view) gzip_response = GZipMiddleware(preserve_version) - return gzip_response(self.request) + response = gzip_response(self.request) + if not isinstance(response, HttpResponse): + raise TypeError("Synchronous middleware returned a non-HTTP response") + return response def test_preserves_job_and_po_versions_before_gzip_weakens_etag(self) -> None: for strong_etag in ( From b88dd9050874b6816b60e64ba036910e02e0718a Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 15:24:08 +1200 Subject: [PATCH 14/39] fix: type resource version response headers --- frontend/src/api/client.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index acaa36d89..606cb8689 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -1,5 +1,5 @@ import { Zodios } from '@zodios/core' -import axios from 'axios' +import axios, { type AxiosResponseHeaders, type RawAxiosResponseHeaders } from 'axios' import { endpoints } from './generated/api' import debug from 'debug' import { trimStringsDeep } from '../utils/sanitize' @@ -19,10 +19,7 @@ import { getSessionReplayId } from '@/services/sessionReplayState' const log = debug('api:client') -type ResourceVersionHeaders = { - 'x-resource-version'?: unknown - etag?: unknown -} +type ResourceVersionHeaders = AxiosResponseHeaders | RawAxiosResponseHeaders function strongHeaderValue(value: unknown): string | null { if (typeof value !== 'string') { From 430a31489db793e6215300d557eda3362820d419 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 16:11:58 +1200 Subject: [PATCH 15/39] fix: unify job person concurrency path --- apps/company/__init__.py | 6 - apps/company/serializers.py | 16 -- apps/company/services/company_rest_service.py | 123 --------------- apps/company/tests/test_contact_methods.py | 48 ------ apps/company/tests/test_job_contact_view.py | 101 ------------- apps/company/urls_rest.py | 7 - apps/company/views/__init__.py | 2 - apps/company/views/company_rest_views.py | 143 ------------------ docs/urls/company.md | 1 - frontend/schema.yml | 122 --------------- frontend/src/api/generated/api.ts | 71 --------- frontend/src/components/PersonSelector.vue | 10 +- .../src/components/job/JobSettingsTab.vue | 51 ++----- .../JobSettingsTab.companyChange.test.ts | 1 - .../JobSettingsTab.labourRate.test.ts | 1 - .../__tests__/JobSettingsTab.urgent.test.ts | 1 - frontend/tests/job/edit-job-settings.spec.ts | 49 ++++++ 17 files changed, 68 insertions(+), 685 deletions(-) delete mode 100644 apps/company/tests/test_job_contact_view.py diff --git a/apps/company/__init__.py b/apps/company/__init__.py index 2b2841847..bdf686e35 100644 --- a/apps/company/__init__.py +++ b/apps/company/__init__.py @@ -57,9 +57,6 @@ CompanyUpdateResponseSerializer, CompanyUpdateSerializer, ContactMethodSerializer, - JobPersonBaseSerializer, - JobPersonResponseSerializer, - JobPersonUpdateSerializer, StandardErrorSerializer, SupplierPickupAddressSerializer, SupplierSearchAliasCreateSerializer, @@ -100,9 +97,6 @@ "CompanyUpdateSerializer", "ContactMethod", "ContactMethodSerializer", - "JobPersonBaseSerializer", - "JobPersonResponseSerializer", - "JobPersonUpdateSerializer", "Person", "PersonCompanyLinkSerializer", "PersonCompanySummarySerializer", diff --git a/apps/company/serializers.py b/apps/company/serializers.py index 7fd91de03..444c89c49 100644 --- a/apps/company/serializers.py +++ b/apps/company/serializers.py @@ -529,22 +529,6 @@ class CompanyUpdateResponseSerializer(serializers.Serializer): message = serializers.CharField() -class JobPersonBaseSerializer(serializers.Serializer): - """Fields shared by the job person response and update serializers.""" - - id = serializers.UUIDField() - name = serializers.CharField() - email = serializers.CharField(allow_blank=True, allow_null=True) - - -class JobPersonResponseSerializer(JobPersonBaseSerializer): - """Serializer for job person information response""" - - -class JobPersonUpdateSerializer(JobPersonBaseSerializer): - """Serializer for job person update request""" - - class CompanyJobHeaderSerializer(serializers.Serializer): """Serializer for job header in company jobs list.""" diff --git a/apps/company/services/company_rest_service.py b/apps/company/services/company_rest_service.py index 94b74741a..e982d12b5 100644 --- a/apps/company/services/company_rest_service.py +++ b/apps/company/services/company_rest_service.py @@ -14,8 +14,6 @@ if TYPE_CHECKING: from django_stubs_ext import WithAnnotations - from apps.accounts.models import Staff - from django.core.exceptions import ValidationError as DjangoValidationError from django.db import transaction from django.db.models import Case, IntegerField, Q, When @@ -453,127 +451,6 @@ def get_company_contacts(company_id: UUID) -> List[Dict[str, Any]]: ) raise - @staticmethod - def get_job_person(job_id: UUID) -> Dict[str, Any]: - """ - Retrieves person information for a specific job. - - Args: - job_id: Job UUID - - Returns: - Dict with person information - - Raises: - ValueError: If job not found or no person associated - """ - # Import here to avoid circular imports - from apps.job.models import Job - - try: - job = Job.objects.select_related("person").get(id=job_id) - except Job.DoesNotExist as exc: - raise ValueError(f"Job with id {job_id} not found") from exc - except Exception as exc: - persist_app_error( - exc, - additional_context={ - "operation": "get_job_person", - "job_id": str(job_id), - }, - ) - raise - - if not job.person: - # Documented business validation failure should not be persisted - raise ValueError(f"No person associated with job {job_id}") - - person = job.person - try: - return { - "id": str(person.id), - "name": person.name, - "email": person.email, - } - except Exception as exc: - persist_app_error( - exc, - additional_context={ - "operation": "serialize_job_person", - "job_id": str(job_id), - }, - ) - raise - - @staticmethod - def update_job_person( - job_id: UUID, person_data: Dict[str, Any], user: "Staff" - ) -> Dict[str, Any]: - """ - Updates the person for a specific job. - - Args: - job_id: Job UUID - person_data: Person data to update - user: Staff performing the update - - Returns: - Dict with updated contact information - - Raises: - ValueError: If job not found, person not found, or validation fails - """ - try: - # Import here to avoid circular imports - from apps.company.models import Person - from apps.job.models import Job - - try: - job = Job.objects.select_related("company", "person").get(id=job_id) - except Job.DoesNotExist as exc: - raise ValueError(f"Job with id {job_id} not found") from exc - - person_id = person_data.get("id") - if not person_id: - raise ValueError("Person ID is required") - - try: - person = Person.objects.get(id=person_id) - except Person.DoesNotExist as exc: - raise ValueError(f"Person with id {person_id} not found") from exc - - job.person = person - job.save(staff=user) - - logger.info( - f"Person {person_id} assigned to job {job_id}", - extra={ - "job_id": str(job_id), - "person_id": str(person_id), - "company_id": str(job.company_id), - "operation": "update_job_person", - }, - ) - - return { - "id": str(person.id), - "name": person.name, - "email": person.email, - } - - except ValueError: - raise - except Exception as exc: - persist_app_error( - exc, - additional_context={ - "operation": "update_job_person", - "job_id": str(job_id), - "person_id": person_data.get("id"), - }, - ) - raise - @staticmethod def _execute_company_search(query: str, limit: int): """ diff --git a/apps/company/tests/test_contact_methods.py b/apps/company/tests/test_contact_methods.py index 8cfe3628d..40dd59c44 100644 --- a/apps/company/tests/test_contact_methods.py +++ b/apps/company/tests/test_contact_methods.py @@ -1,5 +1,4 @@ import uuid -from typing import TYPE_CHECKING from unittest.mock import MagicMock, patch from django.conf import settings @@ -11,9 +10,6 @@ from nplusone.core.profiler import Profiler from nplusone.ext.django.patch import apply_patches -if TYPE_CHECKING: - from apps.job.models import Job - from apps.company.models import Company, CompanyPersonLink, ContactMethod, Person from apps.company.services.company_rest_service import CompanyRestService from apps.crm.models import PhoneCallRecord @@ -329,50 +325,6 @@ def test_contact_annotation_returns_contact_primary_phone(self) -> None: self.assertEqual(annotated.phone, "021 222 222") -class UpdateJobContactTests(BaseTestCase): - """Guards that reassigning a job's contact persists to the job record.""" - - def _job_with_contact(self) -> "tuple[Job, Company, CompanyPersonLink]": - from apps.job.models import Job - from apps.workflow.models import XeroPayItem - - company = Company.objects.create( - name="Acme Ltd", xero_last_modified=timezone.now() - ) - contact = _link(company, "Jane Smith") - job: Job = Job.objects.create( - name="Contact Assignment Job", - company=company, - person=contact.person, - created_by=self.test_staff, - default_xero_pay_item=XeroPayItem.get_ordinary_time(), - staff=self.test_staff, - ) - return job, company, contact - - def test_update_job_person_persists_new_person(self) -> None: - job, company, _ = self._job_with_contact() - new_contact = _link(company, "Bob Brown") - - CompanyRestService.update_job_person( - job.id, {"id": str(new_contact.person_id)}, self.test_staff - ) - - job.refresh_from_db() - self.assertEqual(job.person_id, new_contact.person_id) - - def test_update_job_person_missing_person_is_business_error(self) -> None: - job, _company, _ = self._job_with_contact() - app_error_count = AppError.objects.count() - - with self.assertRaises(ValueError): - CompanyRestService.update_job_person( - job.id, {"id": str(uuid.uuid4())}, self.test_staff - ) - - self.assertEqual(AppError.objects.count(), app_error_count) - - class CompanyListPhoneTests(TestCase): """Guards the Phone column of the companies list (restored after the ContactMethod migration dropped it).""" diff --git a/apps/company/tests/test_job_contact_view.py b/apps/company/tests/test_job_contact_view.py deleted file mode 100644 index e4eb101e9..000000000 --- a/apps/company/tests/test_job_contact_view.py +++ /dev/null @@ -1,101 +0,0 @@ -"""Job person endpoint tests. - -Guards the GET/PUT contract of the job-person endpoint end-to-end (URL -routing, permissions, and response-serializer validation), which the -job-settings tab uses to load and reassign a job's person. -""" - -from typing import TYPE_CHECKING, Any - -from django.urls import reverse -from django.utils import timezone - -if TYPE_CHECKING: - from rest_framework.response import _MonkeyPatchedResponse - -from apps.company.models import Company, CompanyPersonLink, Person -from apps.job.models import Job -from apps.testing import BaseAPITestCase -from apps.workflow.models import XeroPayItem - - -class JobPersonViewTests(BaseAPITestCase): - def setUp(self) -> None: - super().setUp() - self.client.force_authenticate(user=self.test_staff) - self.job_company = Company.objects.create( - name="Acme Ltd", xero_last_modified=timezone.now() - ) - - def _link(self, name: str) -> CompanyPersonLink: - person = Person.objects.create(name=name) - return CompanyPersonLink.objects.create( - company=self.job_company, - person=person, - ) - - def _job(self, link: CompanyPersonLink) -> Job: - job: Job = Job.objects.create( - name="Person Job", - company=self.job_company, - person=link.person, - created_by=self.test_staff, - default_xero_pay_item=XeroPayItem.get_ordinary_time(), - staff=self.test_staff, - ) - return job - - def _url(self, job: Job) -> str: - return reverse("companies:job_person_rest", kwargs={"job_id": job.id}) - - def _get(self, job: Job) -> "_MonkeyPatchedResponse": - return self.client.get(self._url(job)) - - def _put(self, job: Job, payload: dict[str, Any]) -> "_MonkeyPatchedResponse": - return self.client.put(self._url(job), payload, format="json") - - def _put_payload(self, link: CompanyPersonLink) -> dict[str, Any]: - return { - "id": str(link.person_id), - "name": link.person.name, - "email": link.person.email, - } - - def test_get_returns_job_person(self) -> None: - link = self._link("Jane Smith") - job = self._job(link) - - response = self._get(job) - - self.assertEqual(response.status_code, 200) - body = response.json() - self.assertEqual(body["id"], str(link.person_id)) - self.assertEqual(body["name"], "Jane Smith") - - def test_put_response_reflects_new_person(self) -> None: - job = self._job(self._link("Jane Smith")) - replacement = self._link("Bob Jones") - - response = self._put(job, self._put_payload(replacement)) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json()["id"], str(replacement.person_id)) - job.refresh_from_db() - self.assertEqual(job.person_id, replacement.person_id) - - def test_put_ignores_unrecognized_field(self) -> None: - """Phones live in ContactMethod; the job person update path - only reassigns the person FK. An unexpected key (here the removed - phone field) must be ignored, not written or echoed back.""" - job = self._job(self._link("Jane Smith")) - replacement = self._link("Bob Jones") - payload = self._put_payload(replacement) | {"phone": "09 999 9999"} - - response = self._put(job, payload) - - self.assertEqual(response.status_code, 200) - body = response.json() - self.assertEqual(body["id"], str(replacement.person_id)) - self.assertNotIn("phone", body) - job.refresh_from_db() - self.assertEqual(job.person_id, replacement.person_id) diff --git a/apps/company/urls_rest.py b/apps/company/urls_rest.py index 73be36ea4..eab4e7267 100644 --- a/apps/company/urls_rest.py +++ b/apps/company/urls_rest.py @@ -18,7 +18,6 @@ CompanyRetrieveRestView, CompanySearchRestView, CompanyUpdateRestView, - JobPersonRestView, ) from apps.company.views.contact_method_viewset import ContactMethodViewSet from apps.company.views.person_views import ( @@ -103,12 +102,6 @@ SupplierAliasDetailView.as_view(), name="supplier_alias_detail_rest", ), - # Job person REST endpoint - path( - "jobs//person/", - JobPersonRestView.as_view(), - name="job_person_rest", - ), # Address validation endpoint path( "addresses/validate/", diff --git a/apps/company/views/__init__.py b/apps/company/views/__init__.py index 8f75491e6..f356a43a4 100644 --- a/apps/company/views/__init__.py +++ b/apps/company/views/__init__.py @@ -8,7 +8,6 @@ CompanyRetrieveRestView, CompanySearchRestView, CompanyUpdateRestView, - JobPersonRestView, ) from .person_views import ( CompanyPeopleView, @@ -49,7 +48,6 @@ "CompanySupplierAliasListCreateView", "CompanyUpdateRestView", "ContactMethodViewSet", - "JobPersonRestView", "PersonArchiveView", "PersonCompanyLinkDetailView", "PersonCompanyLinksView", diff --git a/apps/company/views/company_rest_views.py b/apps/company/views/company_rest_views.py index 30c291807..8fbed3700 100644 --- a/apps/company/views/company_rest_views.py +++ b/apps/company/views/company_rest_views.py @@ -10,7 +10,6 @@ import logging from typing import Any, Dict -from uuid import UUID from drf_spectacular.utils import ( OpenApiParameter, @@ -24,7 +23,6 @@ from rest_framework.response import Response from rest_framework.views import APIView -from apps.accounts.models import Staff from apps.company.models import Company, ContactMethod from apps.company.serializers import ( CompanyCreateResponseSerializer, @@ -38,8 +36,6 @@ CompanySearchResponseSerializer, CompanyUpdateResponseSerializer, CompanyUpdateSerializer, - JobPersonResponseSerializer, - JobPersonUpdateSerializer, ) from apps.company.services.company_rest_service import CompanyRestService from apps.workflow.services.error_persistence import persist_app_error @@ -497,145 +493,6 @@ def post(self, request: Request) -> Response: ) -@extend_schema_view( - get=extend_schema( - summary="Get job person", - description="Retrieve person information for a specific job.", - parameters=[ - OpenApiParameter( - name="job_id", - location=OpenApiParameter.PATH, - description="UUID of the job", - required=True, - type=OpenApiTypes.UUID, - ) - ], - responses={ - 200: JobPersonResponseSerializer, - 404: CompanyErrorResponseSerializer, - 500: CompanyErrorResponseSerializer, - }, - tags=["Companies"], - ), - put=extend_schema( - summary="Update job person", - description="Update the person associated with a specific job.", - parameters=[ - OpenApiParameter( - name="job_id", - location=OpenApiParameter.PATH, - description="UUID of the job", - required=True, - type=OpenApiTypes.UUID, - ) - ], - request=JobPersonUpdateSerializer, - responses={ - 200: JobPersonResponseSerializer, - 400: CompanyErrorResponseSerializer, - 404: CompanyErrorResponseSerializer, - 500: CompanyErrorResponseSerializer, - }, - tags=["Companies"], - operation_id="companies_jobs_person_update", - ), -) -class JobPersonRestView(APIView): - """ - REST view for person information operations for a job. - Handles both retrieving and updating the person associated with a specific job. - """ - - permission_classes = [IsAuthenticated] - serializer_class = JobPersonResponseSerializer - - def get_serializer_class(self): - """Return the appropriate serializer class based on the request method""" - if self.request.method == "PUT": - return JobPersonUpdateSerializer - return JobPersonResponseSerializer - - def get(self, request: Request, job_id: UUID) -> Response: - """ - Retrieves person information for a specific job. - """ - try: - # Guard clause: validate job_id - if not job_id: - error_serializer = CompanyErrorResponseSerializer( - data={"error": "Job ID is required"} - ) - error_serializer.is_valid(raise_exception=True) - return Response( - error_serializer.data, status=status.HTTP_400_BAD_REQUEST - ) - - person_data = CompanyRestService.get_job_person(job_id) - serializer = JobPersonResponseSerializer(data=person_data) - serializer.is_valid(raise_exception=True) - return Response(serializer.data) - - except ValueError as e: - error_serializer = CompanyErrorResponseSerializer(data={"error": str(e)}) - error_serializer.is_valid(raise_exception=True) - return Response(error_serializer.data, status=status.HTTP_404_NOT_FOUND) - except Exception as exc: - return _build_server_error_response( - message="Error retrieving job person", exc=exc - ) - - def put(self, request: Request, job_id: UUID) -> Response: - """ - Updates the person for a specific job. - """ - try: - # Guard clause: validate job_id - if not job_id: - error_serializer = CompanyErrorResponseSerializer( - data={"error": "Job ID is required"} - ) - error_serializer.is_valid(raise_exception=True) - return Response( - error_serializer.data, status=status.HTTP_400_BAD_REQUEST - ) - - # Validate input data - input_serializer = JobPersonUpdateSerializer(data=request.data) - if not input_serializer.is_valid(): - error_serializer = CompanyErrorResponseSerializer( - data={"error": f"Invalid input data: {input_serializer.errors}"} - ) - error_serializer.is_valid(raise_exception=True) - return Response( - error_serializer.data, status=status.HTTP_400_BAD_REQUEST - ) - - person_data = input_serializer.validated_data - if not isinstance(request.user, Staff): - error_serializer = CompanyErrorResponseSerializer( - data={"error": "Authentication required"} - ) - error_serializer.is_valid(raise_exception=True) - return Response( - error_serializer.data, status=status.HTTP_401_UNAUTHORIZED - ) - updated_person = CompanyRestService.update_job_person( - job_id, person_data, request.user - ) - serializer = JobPersonResponseSerializer(data=updated_person) - serializer.is_valid(raise_exception=True) - return Response(serializer.data) - - except ValueError as e: - error_serializer = CompanyErrorResponseSerializer(data={"error": str(e)}) - error_serializer.is_valid(raise_exception=True) - return Response(error_serializer.data, status=status.HTTP_404_NOT_FOUND) - except Exception as exc: - return _build_server_error_response( - message="Error updating job person", exc=exc - ) - - @extend_schema_view( get=extend_schema( summary="Get company jobs", diff --git a/docs/urls/company.md b/docs/urls/company.md index f47a5bdaa..fe3feba4e 100644 --- a/docs/urls/company.md +++ b/docs/urls/company.md @@ -44,7 +44,6 @@ | URL Pattern | View | Name | Description | |-------------|------|------|-------------| | `//jobs/` | `company_rest_views.CompanyJobsRestView` | `companies:company_jobs_rest` | REST view for fetching all jobs for a specific company. | -| `/jobs//person/` | `company_rest_views.JobPersonRestView` | `companies:job_person_rest` | REST view for person information operations for a job. | ### Other | URL Pattern | View | Name | Description | diff --git a/frontend/schema.yml b/frontend/schema.yml index 087dfb262..e372b6b50 100644 --- a/frontend/schema.yml +++ b/frontend/schema.yml @@ -1856,95 +1856,6 @@ paths: schema: $ref: '#/components/schemas/CompanyErrorResponse' description: '' - /api/companies/jobs/{job_id}/person/: - get: - operationId: companies_jobs_person_retrieve - description: Retrieve person information for a specific job. - summary: Get job person - parameters: - - in: path - name: job_id - schema: - type: string - format: uuid - description: UUID of the job - required: true - tags: - - Companies - security: - - cookieAuth: [] - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/JobPersonResponse' - description: '' - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyErrorResponse' - description: '' - '500': - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyErrorResponse' - description: '' - put: - operationId: companies_jobs_person_update - description: Update the person associated with a specific job. - summary: Update job person - parameters: - - in: path - name: job_id - schema: - type: string - format: uuid - description: UUID of the job - required: true - tags: - - Companies - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/JobPersonUpdateRequest' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/JobPersonUpdateRequest' - multipart/form-data: - schema: - $ref: '#/components/schemas/JobPersonUpdateRequest' - required: true - security: - - cookieAuth: [] - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/JobPersonResponse' - description: '' - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyErrorResponse' - description: '' - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyErrorResponse' - description: '' - '500': - content: - application/json: - schema: - $ref: '#/components/schemas/CompanyErrorResponse' - description: '' /api/companies/pickup-addresses/: get: operationId: companies_pickup_addresses_list @@ -15027,39 +14938,6 @@ components: - total_actual_profit - total_estimated_profit - total_profit - JobPersonResponse: - type: object - description: Serializer for job person information response - properties: - id: - type: string - format: uuid - name: - type: string - email: - type: string - nullable: true - required: - - email - - id - - name - JobPersonUpdateRequest: - type: object - description: Serializer for job person update request - properties: - id: - type: string - format: uuid - name: - type: string - minLength: 1 - email: - type: string - nullable: true - required: - - email - - id - - name JobProfitabilityItem: type: object description: Per-job profitability data. diff --git a/frontend/src/api/generated/api.ts b/frontend/src/api/generated/api.ts index 91c76659b..011dc2658 100644 --- a/frontend/src/api/generated/api.ts +++ b/frontend/src/api/generated/api.ts @@ -830,16 +830,6 @@ const CompanyDuplicateErrorResponse = z.object({ error: z.string(), existing_company: z.object({}).partial().passthrough(), }) -const JobPersonResponse = z.object({ - id: z.string().uuid(), - name: z.string(), - email: z.string().nullable(), -}) -const JobPersonUpdateRequest = z.object({ - id: z.string().uuid(), - name: z.string().min(1), - email: z.string().nullable(), -}) const SupplierPickupAddress = z.object({ id: z.string().uuid(), company: z.string().uuid(), @@ -3841,8 +3831,6 @@ export const schemas = { CompanySearchResult, CompanyCreateResponse, CompanyDuplicateErrorResponse, - JobPersonResponse, - JobPersonUpdateRequest, SupplierPickupAddress, SupplierPickupAddressRequest, PatchedSupplierPickupAddressRequest, @@ -5477,65 +5465,6 @@ Endpoint: /api/app-errors/<id>/`, }, ], }, - { - method: 'get', - path: '/api/companies/jobs/:job_id/person/', - alias: 'companies_jobs_person_retrieve', - description: `Retrieve person information for a specific job.`, - requestFormat: 'json', - parameters: [ - { - name: 'job_id', - type: 'Path', - schema: z.string().uuid(), - }, - ], - response: JobPersonResponse, - errors: [ - { - status: 404, - schema: CompanyErrorResponse, - }, - { - status: 500, - schema: CompanyErrorResponse, - }, - ], - }, - { - method: 'put', - path: '/api/companies/jobs/:job_id/person/', - alias: 'companies_jobs_person_update', - description: `Update the person associated with a specific job.`, - requestFormat: 'json', - parameters: [ - { - name: 'body', - type: 'Body', - schema: JobPersonUpdateRequest, - }, - { - name: 'job_id', - type: 'Path', - schema: z.string().uuid(), - }, - ], - response: JobPersonResponse, - errors: [ - { - status: 400, - schema: CompanyErrorResponse, - }, - { - status: 404, - schema: CompanyErrorResponse, - }, - { - status: 500, - schema: CompanyErrorResponse, - }, - ], - }, { method: 'get', path: '/api/companies/pickup-addresses/', diff --git a/frontend/src/components/PersonSelector.vue b/frontend/src/components/PersonSelector.vue index 497252d6f..df525c534 100644 --- a/frontend/src/components/PersonSelector.vue +++ b/frontend/src/components/PersonSelector.vue @@ -94,12 +94,14 @@ const props = withDefaults( companyName: string modelValue?: string initialPersonId?: string + autoSelectPrimary?: boolean }>(), { placeholder: 'No person selected', optional: true, modelValue: '', initialPersonId: '', + autoSelectPrimary: true, }, ) @@ -339,8 +341,8 @@ watch( ) watch( - () => [props.companyId, props.initialPersonId], - async ([companyId, initialId]) => { + () => [props.companyId, props.initialPersonId, props.autoSelectPrimary] as const, + async ([companyId, initialId, autoSelectPrimary]) => { log('unified watch:', { companyId, initialId }) // Clear local selection without emitting when the company changes. @@ -364,14 +366,14 @@ watch( // Selection priority: // 1) If initialId provided → select that person - // 2) Else if primary person exists → select primary + // 2) Else if enabled and a primary person exists → select primary // 3) Else → clear selection // NOTE: suppressEmit=true prevents API calls during initialization/company change // (auto-selection should not trigger saves - only user actions should) const decideAndSelect = () => { const choose = (initialId && people.value.find((person) => person.person_id === initialId)) || - (!initialId && findPrimaryPerson()) || + (!initialId && autoSelectPrimary && findPrimaryPerson()) || null suppressEmit.value = true diff --git a/frontend/src/components/job/JobSettingsTab.vue b/frontend/src/components/job/JobSettingsTab.vue index ffb6befe7..ed42b1c0f 100644 --- a/frontend/src/components/job/JobSettingsTab.vue +++ b/frontend/src/components/job/JobSettingsTab.vue @@ -167,6 +167,7 @@ :initial-person-id=" typeof localJobData.person_id === 'string' ? localJobData.person_id : undefined " + :auto-select-primary="false" v-model="personDisplayValue" @update:selected-person="handlePersonSelected" /> @@ -1137,11 +1138,11 @@ const handleCompanyUpdated = (updatedCompany: Company) => { toast.success('Company updated successfully') } -const handlePersonSelected = async (personLink: CompanyPerson | null) => { +const handlePersonSelected = (personLink: CompanyPerson | null) => { if (personLink) { - // Skip API call if person is already set to this value + // Skip save if person is already set to this value // This handles: - // - Scenario 4: Company change - backend sets person in response, no duplicate API call needed + // - Company change: backend sets person in response, no duplicate save needed // - User re-selecting the same person if (localJobData.value.person_id === personLink.person_id) { // Still update display value in case it's stale @@ -1158,28 +1159,9 @@ const handlePersonSelected = async (personLink: CompanyPerson | null) => { localJobData.value.person_name = personLink.person_name personDisplayValue.value = personLink.person_name - // Ensure all fields are present for Zod validation (convert undefined to null) - const personToSend = { - id: personLink.person_id, - name: personLink.person_name, - email: personLink.person_email ?? null, - } satisfies z.input - - // Save person directly (not through header autosave) - try { - await api.companies_jobs_person_update(personToSend, { - params: { job_id: props.jobId }, - }) - serverBaseline.value.person_id = personLink.person_id - serverBaseline.value.person_name = personLink.person_name - jobsStore.patchHeader(props.jobId, { - person_id: personLink.person_id, - person_name: personLink.person_name, - }) - toast.success('Person updated successfully') - } catch (error) { - toast.error('Failed to update person') - console.error('Failed to update person:', error) + if (!isInitializing.value && !isHydratingBasicInfo.value && !isSyncingFromStore.value) { + autosave.queueChange('person_id', personLink.person_id) + void autosave.flush('person-select') } } else { localJobData.value.person_id = null @@ -1187,10 +1169,7 @@ const handlePersonSelected = async (personLink: CompanyPerson | null) => { personDisplayValue.value = '' if (!isInitializing.value && !isHydratingBasicInfo.value && !isSyncingFromStore.value) { - autosave.queueChanges({ - person_id: null, - person_name: null, - }) + autosave.queueChange('person_id', null) void autosave.flush('person-clear') } } @@ -1466,13 +1445,11 @@ const autosave = createJobAutosave({ } if (touchedKeys.includes('person_id')) { nextBaseline.person_id = serverJobDetail.person_id ?? null - localJobData.value.person_id = serverJobDetail.person_id ?? null - headerPatch.person_id = serverJobDetail.person_id ?? null - } - if (touchedKeys.includes('person_name')) { nextBaseline.person_name = serverJobDetail.person_name ?? null + localJobData.value.person_id = serverJobDetail.person_id ?? null localJobData.value.person_name = serverJobDetail.person_name ?? null personDisplayValue.value = serverJobDetail.person_name ?? '' + headerPatch.person_id = serverJobDetail.person_id ?? null headerPatch.person_name = serverJobDetail.person_name ?? null } } else { @@ -1588,15 +1565,13 @@ const autosave = createJobAutosave({ } if (touchedKeys.includes('person_id')) { const personId = coerceNullableString(partialPayload.person_id) + const personName = personId === null ? null : (localJobData.value.person_name ?? null) nextBaseline.person_id = personId - localJobData.value.person_id = personId - headerPatch.person_id = personId - } - if (touchedKeys.includes('person_name')) { - const personName = coerceNullableString(partialPayload.person_name) nextBaseline.person_name = personName + localJobData.value.person_id = personId localJobData.value.person_name = personName personDisplayValue.value = personName ?? '' + headerPatch.person_id = personId headerPatch.person_name = personName } } diff --git a/frontend/src/components/job/__tests__/JobSettingsTab.companyChange.test.ts b/frontend/src/components/job/__tests__/JobSettingsTab.companyChange.test.ts index 375972f50..c916b789e 100644 --- a/frontend/src/components/job/__tests__/JobSettingsTab.companyChange.test.ts +++ b/frontend/src/components/job/__tests__/JobSettingsTab.companyChange.test.ts @@ -76,7 +76,6 @@ vi.mock('@/api/client', () => ({ is_urgent: false, }), workflow_xero_pay_items_list: vi.fn().mockResolvedValue([]), - companies_jobs_person_retrieve: vi.fn().mockResolvedValue({ id: null, name: null }), }, })) diff --git a/frontend/src/components/job/__tests__/JobSettingsTab.labourRate.test.ts b/frontend/src/components/job/__tests__/JobSettingsTab.labourRate.test.ts index 3c647742b..49fe87622 100644 --- a/frontend/src/components/job/__tests__/JobSettingsTab.labourRate.test.ts +++ b/frontend/src/components/job/__tests__/JobSettingsTab.labourRate.test.ts @@ -70,7 +70,6 @@ vi.mock('@/api/client', () => ({ is_urgent: false, }), workflow_xero_pay_items_list: vi.fn().mockResolvedValue([]), - companies_jobs_person_retrieve: vi.fn().mockResolvedValue({ id: null, name: null }), }, })) diff --git a/frontend/src/components/job/__tests__/JobSettingsTab.urgent.test.ts b/frontend/src/components/job/__tests__/JobSettingsTab.urgent.test.ts index a1ae53cae..70bdb519e 100644 --- a/frontend/src/components/job/__tests__/JobSettingsTab.urgent.test.ts +++ b/frontend/src/components/job/__tests__/JobSettingsTab.urgent.test.ts @@ -68,7 +68,6 @@ vi.mock('@/api/client', () => ({ is_urgent: true, }), workflow_xero_pay_items_list: vi.fn().mockResolvedValue([]), - companies_jobs_person_retrieve: vi.fn().mockResolvedValue({ id: null, name: null }), }, })) diff --git a/frontend/tests/job/edit-job-settings.spec.ts b/frontend/tests/job/edit-job-settings.spec.ts index f3db35608..84340ac5b 100644 --- a/frontend/tests/job/edit-job-settings.spec.ts +++ b/frontend/tests/job/edit-job-settings.spec.ts @@ -1,4 +1,5 @@ import debug from 'debug' +import { schemas } from '@/api/generated/api' import { test, expect } from '../fixtures/auth' import { getCompanyDefaults } from '../fixtures/api' import { @@ -12,6 +13,12 @@ import { const log = debug('e2e:job') +const getJobIdFromUrl = (url: string): string => { + const match = new URL(url).pathname.match(/\/jobs\/([0-9a-f-]{36})/) + if (!match) throw new Error(`Could not extract job id from ${url}`) + return match[1] +} + const EDIT_JOB_BUDGET_MS = { navigateSettingsTab: 2000, autosave: 1500, @@ -574,6 +581,8 @@ test.describe.serial('edit job', () => { authenticatedPage: page, }) => { const jobUrl = await createTestJob(page, 'Delete Person') + const jobId = getJobIdFromUrl(jobUrl) + const headerUrl = `/api/job/jobs/${jobId}/header/` await page.goto(jobUrl) await page.waitForLoadState('networkidle') @@ -599,6 +608,22 @@ test.describe.serial('edit job', () => { }) }) + // A previous direct person-save path advanced Job.updated_at without refreshing + // the browser's OCC token. Waiting for authoritative selection here makes the + // subsequent archive exercise the real select-then-clear regression. + await expect + .poll( + async () => { + const response = await page.request.get(headerUrl) + if (!response.ok()) { + throw new Error(`Job header read failed: ${response.status()} ${await response.text()}`) + } + return schemas.JobHeaderResponse.parse(await response.json()).person_name + }, + { timeout: 10000 }, + ) + .toBe(personName) + await expectStepUnder( 'reopen modal and delete the person', EDIT_JOB_BUDGET_MS.createOrSwitchPerson, @@ -628,6 +653,30 @@ test.describe.serial('edit job', () => { .filter({ hasText: personName }), ).toHaveCount(0, { timeout: 10000 }) }) + + await test.step('verify the archived person is cleared from the job', async () => { + await expect + .poll( + async () => { + const response = await page.request.get(headerUrl) + if (!response.ok()) { + throw new Error( + `Job header read failed: ${response.status()} ${await response.text()}`, + ) + } + return schemas.JobHeaderResponse.parse(await response.json()).person_id + }, + { timeout: 10000 }, + ) + .toBeNull() + + await page.reload() + await autoId(page, 'JobViewTabs-jobSettings').click() + await autoId(page, 'PersonSelector-display').waitFor({ timeout: 10000 }) + await waitForSettingsInitialized(page) + await page.waitForLoadState('networkidle') + await expect(autoId(page, 'PersonSelector-display')).toHaveValue('') + }) }) test('change company', async ({ authenticatedPage: page }) => { From 723280451cf1fe6ec5241ce79801d7b24e58ae0b Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 16:13:44 +1200 Subject: [PATCH 16/39] chore: shrink mypy baseline --- mypy-baseline.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 4239298a4..18c6e1f06 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -1231,7 +1231,6 @@ apps/company/serializers.py:0: error: Missing type arguments for generic type "S apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/accounting/serializers/rdti_spend_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] @@ -2626,7 +2625,6 @@ apps/company/views/company_rest_views.py:0: error: Function is missing a return apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] From d950123a0a3c400f3f54b5f0c20e80598fa916c2 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Thu, 30 Jul 2026 18:14:59 +1200 Subject: [PATCH 17/39] fix: prevent stale search overriding kanban drag --- .../__tests__/useOptimizedKanban.test.ts | 95 +++++++++++++++++++ .../src/composables/useOptimizedKanban.ts | 12 +++ 2 files changed, 107 insertions(+) diff --git a/frontend/src/composables/__tests__/useOptimizedKanban.test.ts b/frontend/src/composables/__tests__/useOptimizedKanban.test.ts index 9645e8035..3b41cd2d7 100644 --- a/frontend/src/composables/__tests__/useOptimizedKanban.test.ts +++ b/frontend/src/composables/__tests__/useOptimizedKanban.test.ts @@ -1078,6 +1078,101 @@ describe('useOptimizedKanban search reconciliation', () => { expect(reorderJob).toHaveBeenCalledWith('job-1', undefined, undefined, 'draft') }) + it('ignores a stale pre-drag search and applies the committed post-save search', async () => { + // Regression: a slow pre-drag search could restore the old status; resolving both + // generations proves the stale result is ignored and the post-save result wins. + const staleSearch = deferred<{ jobs: ReturnType[] }>() + const committedSearch = deferred<{ jobs: ReturnType[] }>() + const pendingReorder = deferred<{ success: boolean }>() + performAdvancedSearch + .mockReturnValueOnce(staleSearch.promise) + .mockReturnValueOnce(committedSearch.promise) + reorderJob.mockReturnValueOnce(pendingReorder.promise) + + const kanban = await mountHarness() + kanban.searchQuery.value = 'kick' + await kanban.handleSearch() + await vi.advanceTimersByTimeAsync(300) + await flushPromises() + + const reorderPromise = kanban.reorderJob('job-1', undefined, undefined, 'draft', 'drag-race') + + staleSearch.resolve({ + jobs: [ + buildKanbanJob({ + name: 'Stale before drag', + status: 'in_progress', + status_key: 'in_progress', + }), + ], + }) + await flushPromises() + + expect(kanban.filteredJobs.value).toMatchObject([ + { id: 'job-1', status: 'draft', status_key: 'draft' }, + ]) + + pendingReorder.resolve({ success: true }) + await reorderPromise + expect(performAdvancedSearch).toHaveBeenCalledTimes(2) + + committedSearch.resolve({ + jobs: [ + buildKanbanJob({ + name: 'Committed after drag', + status: 'draft', + status_key: 'draft', + }), + ], + }) + await flushPromises() + + expect(kanban.filteredJobs.value).toMatchObject([ + { + id: 'job-1', + name: 'Committed after drag', + status: 'draft', + status_key: 'draft', + }, + ]) + }) + + it('does not keep reorder pending while the post-save search is held', async () => { + // Regression: awaiting search reconciliation made drag persistence feel hung; holding + // that search proves the reorder promise settles independently. + const pendingReorder = deferred<{ success: boolean }>() + const postSaveSearch = deferred<{ jobs: ReturnType[] }>() + performAdvancedSearch + .mockResolvedValueOnce({ jobs: [buildKanbanJob()] }) + .mockReturnValueOnce(postSaveSearch.promise) + reorderJob.mockReturnValueOnce(pendingReorder.promise) + + const kanban = await mountHarness() + kanban.searchQuery.value = 'kick' + await kanban.handleSearch() + await vi.advanceTimersByTimeAsync(300) + await flushPromises() + + let reorderSettled = false + const reorderPromise = kanban + .reorderJob('job-1', undefined, undefined, 'draft', 'drag-background-search') + .then(() => { + reorderSettled = true + }) + + pendingReorder.resolve({ success: true }) + await flushPromises() + + expect(reorderSettled).toBe(true) + expect(performAdvancedSearch).toHaveBeenCalledTimes(2) + + postSaveSearch.resolve({ + jobs: [buildKanbanJob({ status: 'draft', status_key: 'draft' })], + }) + await reorderPromise + await flushPromises() + }) + it('does not force column revalidation after a successful reorder persistence', async () => { const kanban = await mountHarness() diff --git a/frontend/src/composables/useOptimizedKanban.ts b/frontend/src/composables/useOptimizedKanban.ts index d0f8e9a72..20d19ad90 100644 --- a/frontend/src/composables/useOptimizedKanban.ts +++ b/frontend/src/composables/useOptimizedKanban.ts @@ -868,6 +868,10 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { status, }) + if (searchMode.value !== 'none') { + latestSearchRequestId += 1 + } + const targetStatus = status const targetColumnId = targetStatus ? KanbanCategorizationService.getColumnForStatus(targetStatus) @@ -976,6 +980,14 @@ export function useOptimizedKanban(onJobsLoaded?: () => void) { }) await revalidateColumns(columnIds) } + } finally { + void refreshActiveSearch().catch((searchError: unknown) => { + log('kanban.drag.search-reconciliation.error', { + dragId, + jobId, + error: searchError instanceof Error ? searchError.message : String(searchError), + }) + }) } } From dd08050bf08403e4fdd38653c60be0d3be2df7a2 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 09:14:00 +1200 Subject: [PATCH 18/39] fix: skip redundant save when clearing an already-empty person The person-clear branch of handlePersonSelected queued and flushed an autosave unconditionally, unlike the select branch which dedupes on the same value. A server sync can null person_id before PersonSelector emits its own clear, so the clear fired a PATCH that changed nothing and bumped the resource ETag for no reason. Guard the queue/flush on the previous value being non-null, keeping the display resets and the init/hydrate/sync guards unchanged. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Syd6w1ZCbXzFiSex7hbcHn --- .../src/components/job/JobSettingsTab.vue | 12 +++- .../JobSettingsTab.companyChange.test.ts | 56 ++++++++++++++++++- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/job/JobSettingsTab.vue b/frontend/src/components/job/JobSettingsTab.vue index ed42b1c0f..fcbac64e5 100644 --- a/frontend/src/components/job/JobSettingsTab.vue +++ b/frontend/src/components/job/JobSettingsTab.vue @@ -1164,11 +1164,21 @@ const handlePersonSelected = (personLink: CompanyPerson | null) => { void autosave.flush('person-select') } } else { + // Skip save if person is already cleared, mirroring the same-value dedup + // above: a server sync can null person_id before the selector emits its + // own clear, and a redundant PATCH would bump the ETag for no change. + const hadPerson = Boolean(localJobData.value.person_id) + localJobData.value.person_id = null localJobData.value.person_name = null personDisplayValue.value = '' - if (!isInitializing.value && !isHydratingBasicInfo.value && !isSyncingFromStore.value) { + if ( + hadPerson && + !isInitializing.value && + !isHydratingBasicInfo.value && + !isSyncingFromStore.value + ) { autosave.queueChange('person_id', null) void autosave.flush('person-clear') } diff --git a/frontend/src/components/job/__tests__/JobSettingsTab.companyChange.test.ts b/frontend/src/components/job/__tests__/JobSettingsTab.companyChange.test.ts index c916b789e..4057185d6 100644 --- a/frontend/src/components/job/__tests__/JobSettingsTab.companyChange.test.ts +++ b/frontend/src/components/job/__tests__/JobSettingsTab.companyChange.test.ts @@ -2,18 +2,19 @@ import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount, flushPromises } from '@vue/test-utils' import { defineComponent, h } from 'vue' -const { capturedConfig, updateJobHeaderPartial } = vi.hoisted(() => ({ +const { capturedConfig, updateJobHeaderPartial, queueChange } = vi.hoisted(() => ({ capturedConfig: { value: null as { saveAdapter: (patch: Record) => unknown } | null, }, updateJobHeaderPartial: vi.fn(), + queueChange: vi.fn(), })) vi.mock('@/composables/useJobAutosave', () => ({ createJobAutosave: (config: { saveAdapter: (patch: Record) => unknown }) => { capturedConfig.value = config return { - queueChange: vi.fn(), + queueChange, queueChanges: vi.fn(), flush: vi.fn(), cancel: vi.fn(), @@ -177,3 +178,54 @@ describe('JobSettingsTab company-change autosave', () => { expect(Object.keys(payload)).not.toContain('person_name') }) }) + +describe('JobSettingsTab person clear autosave', () => { + const personSelectorStub = defineComponent({ + name: 'PersonSelectorStub', + emits: ['update:selectedPerson', 'update:modelValue'], + setup: () => () => h('div'), + }) + + beforeEach(() => { + vi.clearAllMocks() + }) + + it('saves the first clear but not a repeat clear of an already-empty person', async () => { + const wrapper = mount(JobSettingsTab, { + props: { + jobId: 'job-1', + jobNumber: '101', + pricingMethodology: 'time_materials', + quoted: false, + fullyInvoiced: false, + }, + global: { + stubs: { + Card: passthrough, + CardHeader: passthrough, + CardTitle: passthrough, + CardDescription: passthrough, + CardContent: passthrough, + RichTextEditor: { template: '
' }, + CompanyLookup: { template: '
' }, + PersonSelector: personSelectorStub, + CreateCompanyModal: { template: '
' }, + }, + }, + }) + await flushPromises() + + const selector = wrapper.findComponent(personSelectorStub) + + // Job loads with person-1 set, so the first clear is a real change. + selector.vm.$emit('update:selectedPerson', null) + await flushPromises() + expect(queueChange).toHaveBeenCalledWith('person_id', null) + + // Second clear changes nothing and must not queue a redundant save. + queueChange.mockClear() + selector.vm.$emit('update:selectedPerson', null) + await flushPromises() + expect(queueChange).not.toHaveBeenCalled() + }) +}) From 6d5c2a6251ba6c588c045363ede6a88134df5a91 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 10:01:50 +1200 Subject: [PATCH 19/39] docs: clarify integration and release branches --- CLAUDE.md | 2 +- .../0029-servers-run-the-production-branch.md | 32 ++++++++++++------- docs/adr/README.md | 2 +- docs/updating.md | 9 +++--- scripts/server/README.md | 10 +++--- scripts/server/common.sh | 4 +-- scripts/server/deploy.sh | 8 ++--- 7 files changed, 37 insertions(+), 30 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b201ed784..8d20827fe 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -193,7 +193,7 @@ At the HTTP boundary, read the persisted id with `app_error_for(exc)` to include ## Environment Configuration -See `.env.example` for required environment variables. Key integrations: Xero API, Dropbox, PostgreSQL. Frontend tooling reads `APP_DOMAIN` from the backend `.env` at `../.env` and derives URLs from it (see ADR 0008's Consequences). Deploy uses `scripts/server/deploy.sh` (per-instance `-`); it also runs on boot via systemd so a cold machine catches up to `production`. Servers run the `production` branch by default; `main` is the integration branch — never deployed to production, but deployed to UAT as a release candidate via `deploy.sh --ref` / `instance.sh create --ref` (ADR 0029). +See `.env.example` for required environment variables. Key integrations: Xero API, Dropbox, PostgreSQL. Frontend tooling reads `APP_DOMAIN` from the backend `.env` at `../.env` and derives URLs from it (see ADR 0008's Consequences). Deploy uses `scripts/server/deploy.sh` (per-instance `-`). Testing and UAT servers typically track `main`; production servers typically track `production`. After UAT verification, a release PR promotes `main` to `production` (ADR 0029). ## Migration Management diff --git a/docs/adr/0029-servers-run-the-production-branch.md b/docs/adr/0029-servers-run-the-production-branch.md index 9a92893bb..9b309af98 100644 --- a/docs/adr/0029-servers-run-the-production-branch.md +++ b/docs/adr/0029-servers-run-the-production-branch.md @@ -1,29 +1,37 @@ -# 0029 — Servers run the production branch +# 0029 — Separate integration from production releases -Servers deploy `production` by default; `main` is the integration branch, released by an explicit merge from `main` into `production` and verified on UAT as a candidate (`deploy.sh --ref`) beforehand. +`main` represents integrated work; `production` represents released work. ## Problem -Merging to `main` and deploying to servers were the same event: `deploy.sh` resolved `origin/main`, so anything merged was immediately what the next deploy shipped. A production bug could not be patched without also shipping every unrelated change that had landed on `main` since the last deploy, and long-running structural work (renames, migration squashes) sat between a diagnosed prod bug and its fix. +`main` used to represent both integrated work and the production release. A +production fix therefore also shipped every unrelated change merged since the +previous release. ## Decision -Servers only ever run the `production` branch. All feature PRs target `main` as before. A release is a promotion PR merging `main` → `production`, followed by deploy to UAT, verification, then deploy to prod. A hotfix is a branch cut from `production`, merged into `production` by PR, deployed, and back-merged to `main` immediately so no fix exists only on `production`. Nothing is ever pushed directly to `production`, and no server is ever pointed at any other ref except transiently via `deploy.sh --ref` for candidate verification on UAT. +Feature PRs target `main`. Testing and UAT servers typically track `main`; +production servers typically track `production`. After UAT verification, a +release PR promotes `main` to `production`. + +A hotfix branches from `production`, merges back by PR, deploys, and is +immediately back-merged to `main`. ## Why -Separating "integrated" from "released" makes the deployable state an explicit, deliberate ref instead of a side effect of merge timing. Prod can be patched from exactly what prod runs, regardless of what is in flight on `main`; `main` can absorb large structural work without freezing releases. The promotion merge is also the natural audit point: the diff of the promotion PR is precisely what the fleet is about to receive. Keeping every server (prod, UAT, demo) on the same branch preserves UAT/prod parity — UAT verifies the very ref prod will get, not an approximation. +Separating integrated work from released work lets production be patched +independently of unreleased changes. Each release is also an explicit, +reviewable promotion. ## Alternatives considered -- **Deploy `main` everywhere (status quo):** simplest possible model and fine while the project was one instance with continuous deploys. Wrong once multiple paying instances need patching independently of integration velocity. -- **Release tags instead of a branch:** deploy pinned tags (`prod-YYYY-MM-DD-`). Auditable, but hotfixes need a branch anyway, "latest release" becomes a convention rather than a ref, and every tool that today asks "what should servers run?" needs tag-resolution logic. A branch is the same thing with a stable name. -- **Per-instance release pinning:** each instance records its own ref. Maximum flexibility, but it institutionalises fleet drift; the shared-release directory design (one SHA, many instances) deliberately pushes the other way. +- **Deploy `main` to production:** simpler, but couples production fixes to all + integrated work. +- **Release tags:** auditable, but hotfixes still need a branch and "latest + release" becomes a convention rather than a stable ref. ## Consequences -- Releasing gains one explicit step: the `main` → `production` promotion PR. Deploys themselves are unchanged (`deploy.sh` now resolves `origin/production` by default). -- Hotfixes must be back-merged to `main` in the same working session; a fix that exists only on `production` is a regression waiting to be re-released. +- Releasing gains one explicit step: the `main` → `production` promotion PR. +- Hotfixes must be back-merged to `main` immediately. - `production` carries the same branch protections as `main`. -- Anything that assumes servers track `main` (docs, boot-time catch-up units, operator habit) must say `production` instead. -- `deploy.sh --ref` and `instance.sh create --ref` deploy a candidate ref (e.g. `origin/main`) to UAT; `instance.sh status ` reports which tracked ref a running instance matches. A non-production ref on a `*-prod` instance is refused unless acknowledged — interactive confirm, or `--allow-prod-ref` non-interactively. Nothing persists the ref per instance, so boot-time catch-up still returns UAT to `production`. diff --git a/docs/adr/README.md b/docs/adr/README.md index 71ceea8c1..b49d67196 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -38,7 +38,7 @@ See [`_template.md`](_template.md). Copy, renumber, fill in. | 0026 | Plan the tests before the plan is approved | | 0027 | A capability deploys with the means to operate it | | 0028 | Type annotations are data contracts | -| 0029 | Servers run the production branch | +| 0029 | Separate integration from production releases | | 0030 | First-class People and Company links | | 0031 | One logging gate: the debug library with namespaces | | 0032 | Less code is better: prefer libraries over homegrown implementations | diff --git a/docs/updating.md b/docs/updating.md index 204d60368..2a7755750 100644 --- a/docs/updating.md +++ b/docs/updating.md @@ -28,10 +28,11 @@ If you're running the application locally for development: ## Server Environment (Multi-Tenant) -**This section is the deploy runbook.** Servers only ever run the `production` -branch (ADR 0029): feature PRs merge to `main`, and a release is a promotion PR -merging `main` → `production` (hotfixes PR straight into `production` and are -back-merged to `main`). PR merged to `production`? SSH into the server and run: +**This section is the production deploy runbook.** Feature PRs merge to `main` +and are tested on UAT. After verification, a release PR promotes `main` to +`production`, which production servers typically track (ADR 0029). Hotfixes +merge into `production` and are back-merged to `main`. PR merged to `production`? +SSH into the server and run: ```bash # One client diff --git a/scripts/server/README.md b/scripts/server/README.md index 7b20e7730..e2c2170c1 100644 --- a/scripts/server/README.md +++ b/scripts/server/README.md @@ -133,17 +133,15 @@ What `deploy.sh` does, in order: ### Choosing what to deploy -`deploy.sh` resolves `origin/production` by default. To verify a release -candidate on UAT, deploy any ref explicitly: +Production servers typically track `origin/production`; testing and UAT servers +typically track `origin/main`: ```bash sudo ./scripts/server/deploy.sh mycompany-uat --ref origin/main ``` -`instance.sh create` takes the same `--ref` (default `origin/production`) to -build a new instance's first release from a candidate; re-point an existing -instance with `deploy.sh --ref`. Nothing persists the ref per instance, so -boot-time catch-up returns servers to `production` (ADR 0029). +Use `instance.sh create --ref origin/main` for a new UAT instance; re-point an +existing instance with `deploy.sh --ref`. A non-production `--ref` on a `*-prod` instance is refused unless acknowledged (interactive `y/N`, or `--allow-prod-ref` non-interactively) — a merged hotfix diff --git a/scripts/server/common.sh b/scripts/server/common.sh index 3c5930db9..0f81bcbcf 100755 --- a/scripts/server/common.sh +++ b/scripts/server/common.sh @@ -31,7 +31,7 @@ validate_env() { exit 1 } -# Guard: a prod instance only ever runs origin/production (ADR 0029). A +# Guard: a prod instance normally tracks origin/production (ADR 0029). A # non-production ref on a *-prod instance is almost always an accident (e.g. a # --ref copied from a UAT command), so refuse unless explicitly acknowledged: # interactively with a y/N prompt, or non-interactively with allow="true"/"1". @@ -62,7 +62,7 @@ require_production_ref_or_ack() { fi fi - echo "ERROR: prod instances run origin/production (ADR 0029)." >&2 + echo "ERROR: prod instances normally track origin/production (ADR 0029)." >&2 echo " Pass --allow-prod-ref to override non-interactively." >&2 exit 1 } diff --git a/scripts/server/deploy.sh b/scripts/server/deploy.sh index 2fcbfb1f5..7fb708242 100755 --- a/scripts/server/deploy.sh +++ b/scripts/server/deploy.sh @@ -11,10 +11,10 @@ set -euo pipefail # # That command fetches GitHub, resolves origin/production to a SHA, builds # /opt/docketworks/releases/ if missing, then switches only the requested -# instance to that release. Servers run the production branch by default -# (ADR 0029); main is the integration branch, deployed to UAT only as a -# release candidate via --ref. A non-production --ref on a *-prod instance is -# refused unless acknowledged (interactive confirm, or --allow-prod-ref). +# instance to that release. Production servers typically track production; +# testing and UAT servers typically track main (ADR 0029). A non-production +# --ref on a *-prod instance is refused unless acknowledged (interactive +# confirm, or --allow-prod-ref). SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SELF="$SCRIPT_DIR/$(basename "$0")" From b2cb5eddfdfed6d240fad58e03b7d4c1bf1bcade Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 10:20:40 +1200 Subject: [PATCH 20/39] KAN-316 test: shrink low-hanging mypy debt --- apps/accounts/tests/test_automation_user.py | 4 +- .../job/tests/test_delivery_docket_service.py | 6 +-- apps/job/tests/test_delta_checksum.py | 14 +++--- apps/job/tests/test_job_quote_chat_model.py | 4 +- apps/job/tests/test_paid_flag_service.py | 4 +- .../tests/test_purchase_order_line_usage.py | 6 ++- apps/timesheet/tests/test_pay_run_list_api.py | 19 +++++--- .../tests/test_access_logging_middleware.py | 4 +- apps/workflow/tests/test_xero_tenant_id.py | 6 +-- mypy-baseline.txt | 47 ------------------- 10 files changed, 37 insertions(+), 77 deletions(-) diff --git a/apps/accounts/tests/test_automation_user.py b/apps/accounts/tests/test_automation_user.py index a9413c85a..616c9b91c 100644 --- a/apps/accounts/tests/test_automation_user.py +++ b/apps/accounts/tests/test_automation_user.py @@ -10,7 +10,7 @@ class GetAutomationUserTest(BaseTestCase): seeded identity and the failure mode when the row is absent. """ - def test_returns_seeded_system_automation_user(self): + def test_returns_seeded_system_automation_user(self) -> None: """A seed-data refactor could accidentally make automation privileged. The assertions pin the identity to the system row and prove it cannot @@ -26,7 +26,7 @@ def test_returns_seeded_system_automation_user(self): self.assertFalse(user.is_workshop_staff) self.assertFalse(user.has_usable_password()) - def test_raises_runtime_error_when_row_missing(self): + def test_raises_runtime_error_when_row_missing(self) -> None: """Missing seed data must fail before work is attributed incorrectly. This catches a fallback to an arbitrary staff row or silent ``None`` diff --git a/apps/job/tests/test_delivery_docket_service.py b/apps/job/tests/test_delivery_docket_service.py index f56bd62d7..2c16a2f8d 100644 --- a/apps/job/tests/test_delivery_docket_service.py +++ b/apps/job/tests/test_delivery_docket_service.py @@ -22,7 +22,7 @@ class GenerateDeliveryDocketTests(BaseTestCase): """``generate_delivery_docket`` must attribute its JobEvent to a staff.""" - def setUp(self): + def setUp(self) -> None: super().setUp() # Sandbox the on-disk write so tests don't touch the real Dropbox path. @@ -43,12 +43,12 @@ def setUp(self): staff=self.test_staff, ) - def tearDown(self): + def tearDown(self) -> None: self._settings_override.disable() shutil.rmtree(self._tmp_dropbox, ignore_errors=True) super().tearDown() - def test_generate_attributes_jobevent_to_calling_staff(self): + def test_generate_attributes_jobevent_to_calling_staff(self) -> None: """The emitted JobEvent must carry the staff who triggered the print.""" pdf_buffer, job_file = generate_delivery_docket(self.job, staff=self.test_staff) diff --git a/apps/job/tests/test_delta_checksum.py b/apps/job/tests/test_delta_checksum.py index 6cc9e3a54..e881c7dfd 100644 --- a/apps/job/tests/test_delta_checksum.py +++ b/apps/job/tests/test_delta_checksum.py @@ -7,7 +7,7 @@ from apps.job.services.delta_checksum import compute_job_delta_checksum -def test_checksum_is_deterministic_with_sorted_fields(): +def test_checksum_is_deterministic_with_sorted_fields() -> None: """Field-order differences must not cause false delta conflicts. This catches checksum code that preserves dict insertion order, because the @@ -22,7 +22,7 @@ def test_checksum_is_deterministic_with_sorted_fields(): assert checksum_a == checksum_b -def test_checksum_trims_strings_and_normalises_null(): +def test_checksum_trims_strings_and_normalises_null() -> None: """Equivalent form values must hash the same after canonicalisation. This catches regressions where harmless input padding creates a false @@ -37,7 +37,7 @@ def test_checksum_trims_strings_and_normalises_null(): ) -def test_checksum_handles_decimal_and_boolean_and_numbers(): +def test_checksum_handles_decimal_and_boolean_and_numbers() -> None: """Numeric representation differences must not break optimistic locking. This catches checksum changes that treat ``5.10`` and ``5.100`` as @@ -57,7 +57,7 @@ def test_checksum_handles_decimal_and_boolean_and_numbers(): ) -def test_checksum_handles_datetimes_and_dates(): +def test_checksum_handles_datetimes_and_dates() -> None: """Timezone representation differences must not create false conflicts. This catches UTC-aware and naive-UTC datetimes hashing differently when @@ -75,7 +75,7 @@ def test_checksum_handles_datetimes_and_dates(): ) -def test_checksum_respects_explicit_field_subset(): +def test_checksum_respects_explicit_field_subset() -> None: """Partial deltas must lock only the fields they are changing. This catches checksum code that ignores the requested field subset and @@ -94,7 +94,7 @@ def test_checksum_respects_explicit_field_subset(): assert checksum_all != checksum_subset -def test_checksum_raises_when_job_id_missing(): +def test_checksum_raises_when_job_id_missing() -> None: """A delta without a job identity must not produce a reusable checksum. This catches callers accidentally hashing orphaned field values and then @@ -104,7 +104,7 @@ def test_checksum_raises_when_job_id_missing(): compute_job_delta_checksum("", {"name": "Part A"}) -def test_checksum_raises_for_missing_field_in_subset(): +def test_checksum_raises_for_missing_field_in_subset() -> None: """Requested fields missing from the snapshot must fail before mutation. This catches envelope-building bugs where the checksum omits a field the diff --git a/apps/job/tests/test_job_quote_chat_model.py b/apps/job/tests/test_job_quote_chat_model.py index b93cc4720..6bdca8476 100644 --- a/apps/job/tests/test_job_quote_chat_model.py +++ b/apps/job/tests/test_job_quote_chat_model.py @@ -14,7 +14,7 @@ class JobQuoteChatModelTests(BaseTestCase): """Test JobQuoteChat model constraints""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.company_defaults = CompanyDefaults.get_solo() @@ -34,7 +34,7 @@ def setUp(self): staff=self.test_staff, ) - def test_message_id_uniqueness(self): + def test_message_id_uniqueness(self) -> None: """Test that message_id must be unique""" JobQuoteChat.objects.create( job=self.job, diff --git a/apps/job/tests/test_paid_flag_service.py b/apps/job/tests/test_paid_flag_service.py index e0099bd67..7c6b82894 100644 --- a/apps/job/tests/test_paid_flag_service.py +++ b/apps/job/tests/test_paid_flag_service.py @@ -16,7 +16,7 @@ class PaidFlagServiceTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Paid Flag Company", xero_last_modified=timezone.now(), @@ -48,7 +48,7 @@ def _create_invoice(self, job: Job, status: str) -> Invoice: raw_json={}, ) - def test_update_paid_flags_uses_prefetched_invoices_for_batch(self): + def test_update_paid_flags_uses_prefetched_invoices_for_batch(self) -> None: """Batch paid-flag checks must not lazy-load invoices per job.""" paid_job = self._create_job("Paid Job") unpaid_job = self._create_job("Unpaid Job") diff --git a/apps/purchasing/tests/test_purchase_order_line_usage.py b/apps/purchasing/tests/test_purchase_order_line_usage.py index c64d27519..c1ea53cbe 100644 --- a/apps/purchasing/tests/test_purchase_order_line_usage.py +++ b/apps/purchasing/tests/test_purchase_order_line_usage.py @@ -21,7 +21,7 @@ def company_defaults(db: None) -> None: @pytest.fixture -def auth_api(db, company_defaults): +def auth_api(db: None, company_defaults: None) -> APIClient: staff = Staff.objects.create( email="po-line-usage@example.test", first_name="Purchase", @@ -57,7 +57,9 @@ def _material_usage(item_code: str) -> None: @pytest.mark.django_db -def test_purchase_order_detail_lines_include_material_times_used(auth_api): +def test_purchase_order_detail_lines_include_material_times_used( + auth_api: APIClient, +) -> None: po = PurchaseOrder.objects.create(po_number="PO-USAGE-1") used_line = PurchaseOrderLine.objects.create( purchase_order=po, diff --git a/apps/timesheet/tests/test_pay_run_list_api.py b/apps/timesheet/tests/test_pay_run_list_api.py index 90472a26d..a17bba099 100644 --- a/apps/timesheet/tests/test_pay_run_list_api.py +++ b/apps/timesheet/tests/test_pay_run_list_api.py @@ -1,6 +1,6 @@ import uuid from datetime import date, datetime, timezone -from unittest.mock import patch +from unittest.mock import MagicMock, patch from django.urls import reverse from rest_framework.test import APIClient @@ -11,7 +11,7 @@ class PayRunListApiTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.client_api = APIClient() self.superuser = Staff.objects.create_user( @@ -30,7 +30,10 @@ def setUp(self): self.calendar_id = company.xero_payroll_calendar_id @patch("apps.timesheet.views.api.build_xero_payroll_url") - def test_list_pay_runs_uses_local_mirror_table(self, mock_build_xero_payroll_url): + def test_list_pay_runs_uses_local_mirror_table( + self, + mock_build_xero_payroll_url: MagicMock, + ) -> None: mock_build_xero_payroll_url.return_value = "https://example.test/payrun/1" pay_run = XeroPayRun.objects.create( xero_id=uuid.uuid4(), @@ -57,8 +60,9 @@ def test_list_pay_runs_uses_local_mirror_table(self, mock_build_xero_payroll_url @patch("apps.timesheet.views.api.build_xero_payroll_url") def test_next_postable_week_is_after_latest_run_when_no_draft( - self, mock_build_xero_payroll_url - ): + self, + mock_build_xero_payroll_url: MagicMock, + ) -> None: mock_build_xero_payroll_url.return_value = "https://example.test/payrun/1" XeroPayRun.objects.create( xero_id=uuid.uuid4(), @@ -82,8 +86,9 @@ def test_next_postable_week_is_after_latest_run_when_no_draft( @patch("apps.workflow.api.xero.payroll.get_payroll_calendars") def test_next_postable_week_uses_calendar_anchor_when_no_pay_runs( - self, mock_get_payroll_calendars - ): + self, + mock_get_payroll_calendars: MagicMock, + ) -> None: mock_get_payroll_calendars.return_value = [ { "id": str(self.calendar_id), diff --git a/apps/workflow/tests/test_access_logging_middleware.py b/apps/workflow/tests/test_access_logging_middleware.py index c76d4261e..a44959f8f 100644 --- a/apps/workflow/tests/test_access_logging_middleware.py +++ b/apps/workflow/tests/test_access_logging_middleware.py @@ -9,7 +9,7 @@ @pytest.mark.django_db -def test_access_log_includes_response_status_and_duration(): +def test_access_log_includes_response_status_and_duration() -> None: staff = Staff.objects.create_user( email="access-log@example.test", password="testpass123", @@ -41,7 +41,7 @@ def test_access_log_includes_response_status_and_duration(): assert log_args[6] == "/api/job/kanban/" -def test_access_log_skips_unauthenticated_requests(): +def test_access_log_skips_unauthenticated_requests() -> None: request = RequestFactory().get("/api/job/kanban/") request.user = type("AnonymousUser", (), {"is_authenticated": False})() middleware = AccessLoggingMiddleware(lambda _request: HttpResponse(status=401)) diff --git a/apps/workflow/tests/test_xero_tenant_id.py b/apps/workflow/tests/test_xero_tenant_id.py index 282ec3112..9be5ddcd0 100644 --- a/apps/workflow/tests/test_xero_tenant_id.py +++ b/apps/workflow/tests/test_xero_tenant_id.py @@ -25,14 +25,14 @@ def _active_xero_app() -> None: class XeroTenantIdTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: cache.delete(TENANT_ID_CACHE_KEY) company_defaults = CompanyDefaults.get_solo() company_defaults.xero_tenant_id = "configured-tenant" company_defaults.save(update_fields=["xero_tenant_id"]) _active_xero_app() - def test_get_tenant_id_uses_company_defaults_on_cache_miss(self): + def test_get_tenant_id_uses_company_defaults_on_cache_miss(self) -> None: """Normal Xero calls must not discover the stable tenant over the network.""" from apps.workflow.api.xero.auth import get_tenant_id @@ -43,7 +43,7 @@ def test_get_tenant_id_uses_company_defaults_on_cache_miss(self): assert cache.get(TENANT_ID_CACHE_KEY) == "configured-tenant" mock_identity_api.assert_not_called() - def test_get_tenant_id_uses_cache_before_company_defaults(self): + def test_get_tenant_id_uses_cache_before_company_defaults(self) -> None: """Active-app swaps own cache invalidation; ordinary reads should trust cache.""" from apps.workflow.api.xero.auth import get_tenant_id diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 18c6e1f06..94b6f1b0f 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -30,20 +30,6 @@ apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generi apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/company/utils.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/services/geocoding_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delta_checksum.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delta_checksum.py:0: note: Use "-> None" if function does not return a value docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] @@ -1113,8 +1099,6 @@ apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a re apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_purchase_order_line_usage.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_purchase_order_line_usage.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1498,11 +1482,6 @@ apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a re apps/timesheet/tests/test_payroll_post_api.py:0: note: Use "-> None" if function does not return a value apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/timesheet/tests/test_payroll_post_api.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_pay_run_list_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_pay_run_list_api.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_pay_run_list_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_pay_run_list_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_pay_run_list_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Returning Any from function declared to return "Job" [no-any-return] @@ -1799,10 +1778,6 @@ apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type a apps/job/tests/test_pdf_goldens.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_pdf_goldens.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_paid_flag_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_paid_flag_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_paid_flag_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_paid_flag_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1875,10 +1850,6 @@ apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a retu apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_quote_chat_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_quote_chat_model.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_quote_chat_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_quote_chat_model.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_latest_costsets.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_job_latest_costsets.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_latest_costsets.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1946,12 +1917,6 @@ apps/job/tests/test_job_files_api.py:0: note: Use "-> None" if function does not apps/job/tests/test_job_files_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] apps/job/tests/test_job_files_api.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_job_files_api.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delivery_docket_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delivery_docket_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delivery_docket_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delivery_docket_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_delivery_docket_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_delivery_docket_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_costline_schema_validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] @@ -2046,10 +2011,6 @@ apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a re apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_automation_user.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_automation_user.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_automation_user.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_automation_user.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_sales_pipeline_api.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] apps/accounting/tests/test_sales_pipeline_api.py:0: error: "type[SalesPipelineAPITests]" has no attribute "office_staff" [attr-defined] apps/accounting/tests/test_sales_pipeline_api.py:0: error: "SalesPipelineAPITests" has no attribute "office_staff" [attr-defined] @@ -2948,8 +2909,6 @@ apps/job/services/job_rest_service.py:0: error: Incompatible default for paramet apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] -apps/workflow/tests/test_access_logging_middleware.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_access_logging_middleware.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -3730,12 +3689,6 @@ apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_quote" in typed context [no-untyped-call] apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_purchase_order" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_tenant_id.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_tenant_id.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] From 7271d554b7ebfad026b642a885a194bf62eeacb2 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 10:30:06 +1200 Subject: [PATCH 21/39] KAN-316 test: annotate void test functions --- apps/accounting/tests/test_core_nplusone.py | 6 +- .../tests/test_invoice_calculation.py | 38 +- apps/accounting/tests/test_invoice_models.py | 2 +- .../tests/test_sales_pipeline_api.py | 22 +- .../tests/test_sales_pipeline_service.py | 40 +- .../accounts/tests/test_auth_observability.py | 8 +- apps/accounts/tests/test_displayable_staff.py | 24 +- apps/accounts/tests/test_staff_api.py | 2 +- .../tests/test_company_invoice_summary.py | 4 +- .../tests/test_get_company_for_xero.py | 20 +- apps/job/tests/test_chat_api_endpoints.py | 44 +- apps/job/tests/test_chat_performance.py | 6 +- apps/job/tests/test_chat_service.py | 44 +- apps/job/tests/test_event_deduplication.py | 16 +- apps/job/tests/test_job_event_tracking.py | 90 +- apps/job/tests/test_job_files_api.py | 10 +- apps/job/tests/test_job_invoicing.py | 18 +- apps/job/tests/test_job_latest_costsets.py | 12 +- apps/job/tests/test_job_rest_service.py | 6 +- .../job/tests/test_kanban_reorder_priority.py | 12 +- apps/job/tests/test_kanban_search.py | 76 +- apps/job/tests/test_kanban_service.py | 16 +- apps/job/tests/test_mcp_tool_integration.py | 70 +- apps/job/tests/test_modern_timesheet_views.py | 4 +- apps/job/tests/test_pdf_goldens.py | 4 +- apps/job/tests/test_quote_modes.py | 24 +- apps/job/tests/test_workshop_pdf_service.py | 64 +- .../tests/test_scheduler_persistence.py | 18 +- .../tests/test_scheduler_service.py | 82 +- .../tests/test_workshop_schedule_api.py | 20 +- apps/process/tests/test_form_model.py | 10 +- apps/process/tests/test_form_service.py | 10 +- apps/process/tests/test_procedure_model.py | 8 +- apps/process/tests/test_procedure_service.py | 6 +- apps/purchasing/tests/test_serializers.py | 6 +- .../purchasing/tests/test_stock_fts_search.py | 6 +- apps/purchasing/tests/test_supplier_search.py | 22 +- .../quoting/tests/test_pdf_data_validation.py | 28 +- .../tests/test_daily_timesheet_service.py | 6 +- apps/timesheet/tests/test_payroll_post_api.py | 8 +- apps/timesheet/tests/test_permissions.py | 18 +- .../tests/test_weekly_timesheet_service.py | 4 +- .../tests/test_api_schema_coverage.py | 2 +- .../tests/test_company_defaults_api.py | 6 +- .../tests/test_company_defaults_schema.py | 38 +- apps/workflow/tests/test_dev_demo_export.py | 4 +- .../tests/test_localdate_regression.py | 36 +- apps/workflow/tests/test_search_telemetry.py | 2 +- .../tests/test_seed_xero_from_database.py | 2 +- apps/workflow/tests/test_sync_clients.py | 2 +- apps/workflow/tests/test_xero_app_api.py | 46 +- apps/workflow/tests/test_xero_app_model.py | 10 +- .../tests/test_xero_document_raw_json.py | 6 +- apps/workflow/tests/test_xero_pay_item.py | 4 +- apps/workflow/tests/test_xero_po_manager.py | 2 +- apps/workflow/tests/test_xero_quota_floor.py | 54 +- .../workflow/tests/test_xero_setup_command.py | 2 +- .../test_xero_transform_contact_resolution.py | 2 +- mypy-baseline.txt | 1124 ----------------- 59 files changed, 590 insertions(+), 1686 deletions(-) diff --git a/apps/accounting/tests/test_core_nplusone.py b/apps/accounting/tests/test_core_nplusone.py index 3f0c3faaa..8ec705e5d 100644 --- a/apps/accounting/tests/test_core_nplusone.py +++ b/apps/accounting/tests/test_core_nplusone.py @@ -22,7 +22,7 @@ class AccountingCoreQueryTests(BaseTestCase): rows and a fixed query budget for the report boundary. """ - def setUp(self): + def setUp(self) -> None: super().setUp() self.target_date = date(2026, 5, 22) self.company = Company.objects.create( @@ -75,7 +75,7 @@ def _create_time_line(self, job: Job, staff: Staff, hours: str = "2.000"): entry_seq=1, ) - def test_kpi_job_breakdown_preloads_job_client(self): + def test_kpi_job_breakdown_preloads_job_client(self) -> None: """Job breakdown must not fetch each job's company inside the loop. This catches removing ``select_related("cost_set__job__company")`` by @@ -100,7 +100,7 @@ def test_kpi_job_breakdown_preloads_job_client(self): self.assertEqual(breakdown[0]["company_name"], "Accounting Nplusone Company") - def test_staff_performance_groups_prefetched_cost_lines_by_staff(self): + def test_staff_performance_groups_prefetched_cost_lines_by_staff(self) -> None: """Staff performance must group prefetched lines without per-staff queries. This catches metric code that looks up CostLine/job/company data inside diff --git a/apps/accounting/tests/test_invoice_calculation.py b/apps/accounting/tests/test_invoice_calculation.py index 6cd80aff4..6b20205dd 100644 --- a/apps/accounting/tests/test_invoice_calculation.py +++ b/apps/accounting/tests/test_invoice_calculation.py @@ -24,7 +24,7 @@ class TestInvoiceCalculation(BaseTestCase): """Tests for calculate_invoice_amount().""" - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Test Company", xero_last_modified=timezone.now(), @@ -68,7 +68,7 @@ def _create_invoice(self, job, amount, status="AUTHORISED"): # --- Quoted job: invoice_full --- - def test_quoted_invoice_full_no_prior(self): + def test_quoted_invoice_full_no_prior(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) result = calculate_invoice_amount(job, mode="invoice_full") @@ -77,14 +77,14 @@ def test_quoted_invoice_full_no_prior(self): self.assertEqual(result.target_total, Decimal("5000")) self.assertEqual(result.prior_invoiced_total, Decimal("0")) - def test_quoted_invoice_full_with_prior(self): + def test_quoted_invoice_full_with_prior(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) self._create_invoice(job, Decimal("3000")) result = calculate_invoice_amount(job, mode="invoice_full") self.assertEqual(result.calculated_amount, Decimal("2000")) - def test_quoted_invoice_full_fully_invoiced(self): + def test_quoted_invoice_full_fully_invoiced(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) self._create_invoice(job, Decimal("5000")) @@ -93,7 +93,7 @@ def test_quoted_invoice_full_fully_invoiced(self): # --- Quoted job: invoice_percent --- - def test_quoted_invoice_percent_no_prior(self): + def test_quoted_invoice_percent_no_prior(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) result = calculate_invoice_amount( @@ -101,7 +101,7 @@ def test_quoted_invoice_percent_no_prior(self): ) self.assertEqual(result.calculated_amount, Decimal("2500")) - def test_quoted_invoice_percent_with_prior(self): + def test_quoted_invoice_percent_with_prior(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) self._create_invoice(job, Decimal("1000")) @@ -110,7 +110,7 @@ def test_quoted_invoice_percent_with_prior(self): ) self.assertEqual(result.calculated_amount, Decimal("1500")) - def test_quoted_invoice_percent_missing_percent(self): + def test_quoted_invoice_percent_missing_percent(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) with self.assertRaises(InvoiceCalculationError): @@ -118,7 +118,7 @@ def test_quoted_invoice_percent_missing_percent(self): # --- Quoted job: invoice_amount --- - def test_quoted_invoice_amount_valid(self): + def test_quoted_invoice_amount_valid(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) result = calculate_invoice_amount( @@ -126,7 +126,7 @@ def test_quoted_invoice_amount_valid(self): ) self.assertEqual(result.calculated_amount, Decimal("2000")) - def test_quoted_invoice_amount_exceeds_remaining(self): + def test_quoted_invoice_amount_exceeds_remaining(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) self._create_invoice(job, Decimal("4000")) @@ -135,14 +135,14 @@ def test_quoted_invoice_amount_exceeds_remaining(self): # --- T&M job: invoice_costs_to_date --- - def test_tm_costs_to_date_no_prior(self): + def test_tm_costs_to_date_no_prior(self) -> None: job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("7500")) result = calculate_invoice_amount(job, mode="invoice_costs_to_date") self.assertEqual(result.calculated_amount, Decimal("7500")) self.assertEqual(result.target_basis, "actual_revenue") - def test_tm_costs_to_date_with_prior(self): + def test_tm_costs_to_date_with_prior(self) -> None: job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("7500")) self._create_invoice(job, Decimal("2500")) @@ -151,7 +151,7 @@ def test_tm_costs_to_date_with_prior(self): # --- T&M job: invoice_amount --- - def test_tm_invoice_amount_valid(self): + def test_tm_invoice_amount_valid(self) -> None: job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("7500")) result = calculate_invoice_amount( @@ -161,7 +161,7 @@ def test_tm_invoice_amount_valid(self): # --- T&M job: invalid modes --- - def test_tm_invoice_percent_rejected(self): + def test_tm_invoice_percent_rejected(self) -> None: job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("7500")) with self.assertRaises(InvoiceCalculationError): @@ -169,14 +169,14 @@ def test_tm_invoice_percent_rejected(self): # --- Voided/deleted invoices --- - def test_voided_invoices_excluded_from_prior(self): + def test_voided_invoices_excluded_from_prior(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) self._create_invoice(job, Decimal("3000"), status="VOIDED") result = calculate_invoice_amount(job, mode="invoice_full") self.assertEqual(result.calculated_amount, Decimal("5000")) - def test_deleted_invoices_excluded_from_prior(self): + def test_deleted_invoices_excluded_from_prior(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) self._create_invoice(job, Decimal("3000"), status="DELETED") @@ -185,7 +185,7 @@ def test_deleted_invoices_excluded_from_prior(self): # --- Price cap --- - def test_tm_price_cap_applied(self): + def test_tm_price_cap_applied(self) -> None: job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("10000")) job.price_cap = Decimal("8000") @@ -195,7 +195,7 @@ def test_tm_price_cap_applied(self): # --- Negative/zero rejection --- - def test_zero_invoice_rejected(self): + def test_zero_invoice_rejected(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("0")) with self.assertRaises(InvoiceCalculationError): @@ -203,7 +203,7 @@ def test_zero_invoice_rejected(self): # --- get_prior_valid_invoice_total --- - def test_prior_total_excludes_voided_deleted(self): + def test_prior_total_excludes_voided_deleted(self) -> None: job = self._create_job("fixed_price") self._add_revenue_line(job.latest_quote, Decimal("5000")) self._create_invoice(job, Decimal("1000"), status="AUTHORISED") @@ -212,7 +212,7 @@ def test_prior_total_excludes_voided_deleted(self): total = get_prior_valid_invoice_total(job) self.assertEqual(total, Decimal("1000")) - def test_preloaded_job_calculates_without_lazy_loading_cost_lines(self): + def test_preloaded_job_calculates_without_lazy_loading_cost_lines(self) -> None: """Xero invoice creation preloads CostSet lines before calculation.""" job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("250")) diff --git a/apps/accounting/tests/test_invoice_models.py b/apps/accounting/tests/test_invoice_models.py index 349c49e11..4a94b68d6 100644 --- a/apps/accounting/tests/test_invoice_models.py +++ b/apps/accounting/tests/test_invoice_models.py @@ -10,7 +10,7 @@ class InvoiceModelTests(BaseTestCase): - def test_total_amount_sums_reverse_line_items(self): + def test_total_amount_sums_reverse_line_items(self) -> None: """Guards against ``total_amount`` returning a stale or incorrect value when line items are added or modified — a bug here silently corrupts invoice totals displayed to users and synced to Xero. diff --git a/apps/accounting/tests/test_sales_pipeline_api.py b/apps/accounting/tests/test_sales_pipeline_api.py index 208fbbf1a..9d5232c1c 100644 --- a/apps/accounting/tests/test_sales_pipeline_api.py +++ b/apps/accounting/tests/test_sales_pipeline_api.py @@ -42,7 +42,7 @@ def setUp(self) -> None: def _get(self, params: dict | None = None): return self.client.get(self.url, data=params or {}) - def test_valid_request_returns_all_sections(self): + def test_valid_request_returns_all_sections(self) -> None: resp = self._get( { "start_date": "2026-01-01", @@ -67,37 +67,37 @@ def test_valid_request_returns_all_sections(self): self.assertEqual(len(body["trend"]["weeks"]), 4) self.assertEqual(len(body["trend"]["rolling_average"]), 4) - def test_omitted_end_date_defaults_to_today(self): + def test_omitted_end_date_defaults_to_today(self) -> None: today = timezone.localdate() resp = self._get({"start_date": "2026-01-01"}) self.assertEqual(resp.status_code, status.HTTP_200_OK, resp.content) body = resp.json() self.assertEqual(body["period"]["end_date"], today.isoformat()) - def test_missing_start_date_returns_400(self): + def test_missing_start_date_returns_400(self) -> None: resp = self._get({"end_date": "2026-02-01"}) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) body = resp.json() self.assertIn("details", body) self.assertIn("start_date", body["details"]) - def test_invalid_start_date_returns_400(self): + def test_invalid_start_date_returns_400(self) -> None: resp = self._get({"start_date": "not-a-date"}) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn("start_date", resp.json()["details"]) - def test_invalid_end_date_returns_400(self): + def test_invalid_end_date_returns_400(self) -> None: resp = self._get({"start_date": "2026-01-01", "end_date": "2026-13-40"}) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn("end_date", resp.json()["details"]) - def test_start_after_end_returns_400(self): + def test_start_after_end_returns_400(self) -> None: resp = self._get({"start_date": "2026-02-10", "end_date": "2026-02-01"}) self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) # ``validate()`` surfaces this on end_date per the serializer. self.assertIn("end_date", resp.json()["details"]) - def test_non_positive_rolling_window_returns_400(self): + def test_non_positive_rolling_window_returns_400(self) -> None: resp = self._get( { "start_date": "2026-01-01", @@ -108,7 +108,7 @@ def test_non_positive_rolling_window_returns_400(self): self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn("rolling_window_weeks", resp.json()["details"]) - def test_non_positive_trend_weeks_returns_400(self): + def test_non_positive_trend_weeks_returns_400(self) -> None: resp = self._get( { "start_date": "2026-01-01", @@ -119,7 +119,7 @@ def test_non_positive_trend_weeks_returns_400(self): self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST) self.assertIn("trend_weeks", resp.json()["details"]) - def test_unexpected_service_failure_returns_standard_error_shape(self): + def test_unexpected_service_failure_returns_standard_error_shape(self) -> None: """Unhandled service exceptions must be persisted via ``persist_app_error`` and surfaced as a 500 with the standard error payload (``error`` plus ``details.error_id``).""" @@ -136,7 +136,7 @@ def test_unexpected_service_failure_returns_standard_error_shape(self): self.assertIn("details", body) self.assertIn("error_id", body["details"]) - def test_unauthenticated_request_is_rejected(self): + def test_unauthenticated_request_is_rejected(self) -> None: anon = APIClient() resp = anon.get(self.url, data={"start_date": "2026-01-01"}) self.assertIn( @@ -144,7 +144,7 @@ def test_unauthenticated_request_is_rejected(self): (status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN), ) - def test_default_rolling_window_and_trend_weeks(self): + def test_default_rolling_window_and_trend_weeks(self) -> None: """When only dates are supplied, the serializer fills in the documented defaults (rolling_window_weeks=4, trend_weeks=13).""" start = timezone.localdate() - timedelta(days=30) diff --git a/apps/accounting/tests/test_sales_pipeline_service.py b/apps/accounting/tests/test_sales_pipeline_service.py index 96b62b3b9..14156f9fa 100644 --- a/apps/accounting/tests/test_sales_pipeline_service.py +++ b/apps/accounting/tests/test_sales_pipeline_service.py @@ -142,7 +142,7 @@ def setUp(self) -> None: self.start = date(2026, 3, 2) # Monday self.end = date(2026, 3, 6) # Friday — 5 working days - def test_status_changed_into_approved_counts(self): + def test_status_changed_into_approved_counts(self) -> None: job = self._make_job( name="J1", company=self.client_obj, created_dt=_nz_dt(date(2026, 1, 5)) ) @@ -160,7 +160,7 @@ def test_status_changed_into_approved_counts(self): # Not direct — went through awaiting_approval. self.assertEqual(rep["scoreboard"]["direct_jobs_count"], 0) - def test_quote_accepted_counts(self): + def test_quote_accepted_counts(self) -> None: job = self._make_job( name="J2", company=self.client_obj, created_dt=_nz_dt(date(2026, 1, 5)) ) @@ -174,7 +174,7 @@ def test_quote_accepted_counts(self): self.assertEqual(rep["scoreboard"]["approved_jobs_count"], 1) self.assertAlmostEqual(rep["scoreboard"]["approved_hours_total"], 4.0) - def test_direct_approved_counts_in_direct_bucket(self): + def test_direct_approved_counts_in_direct_bucket(self) -> None: job = self._make_job( name="J3", company=self.client_obj, created_dt=_nz_dt(date(2026, 1, 5)) ) @@ -189,7 +189,7 @@ def test_direct_approved_counts_in_direct_bucket(self): self.assertEqual(rep["scoreboard"]["direct_jobs_count"], 1) self.assertAlmostEqual(rep["scoreboard"]["direct_hours"], 6.0) - def test_dedupe_approved_then_in_progress_same_period(self): + def test_dedupe_approved_then_in_progress_same_period(self) -> None: job = self._make_job( name="J4", company=self.client_obj, created_dt=_nz_dt(date(2026, 1, 5)) ) @@ -208,7 +208,7 @@ def test_dedupe_approved_then_in_progress_same_period(self): self.assertEqual(rep["scoreboard"]["approved_jobs_count"], 1) self.assertAlmostEqual(rep["scoreboard"]["approved_hours_total"], 10.0) - def test_target_reflects_company_defaults(self): + def test_target_reflects_company_defaults(self) -> None: defaults = CompanyDefaults.get_solo() defaults.daily_approved_hours_target = Decimal("20.00") defaults.save() @@ -219,7 +219,7 @@ def test_target_reflects_company_defaults(self): self.assertAlmostEqual(rep["scoreboard"]["target_hours_for_period"], 100.0) self.assertAlmostEqual(rep["period"]["daily_approved_hours_target"], 20.0) - def test_missing_hours_summary_excludes_and_warns(self): + def test_missing_hours_summary_excludes_and_warns(self) -> None: job = self._make_job( name="No hours", company=self.client_obj, @@ -246,7 +246,7 @@ def setUp(self) -> None: super().setUp() self.client_obj = self._make_client() - def test_replays_to_historical_status_not_live(self): + def test_replays_to_historical_status_not_live(self) -> None: # Created in draft 2026-01-05, moved to awaiting_approval 2026-02-01, # approved 2026-03-15, archived 2026-04-10. As of end_date 2026-02-15 # the historical state is "awaiting_approval". @@ -279,7 +279,7 @@ def test_replays_to_historical_status_not_live(self): rep["pipeline_snapshot"]["awaiting_approval"]["hours_total"], 7.0 ) - def test_days_in_stage_uses_most_recent_entry(self): + def test_days_in_stage_uses_most_recent_entry(self) -> None: end_date = date(2026, 3, 20) # Created in awaiting_approval, bounced back to draft, then back to # awaiting_approval. Days-in-stage measured from the latest entry. @@ -308,7 +308,7 @@ def test_days_in_stage_uses_most_recent_entry(self): self.assertEqual(bucket["count"], 1) self.assertEqual(bucket["jobs"][0]["days_in_stage"], 10) - def test_draft_uses_estimate_summary_awaiting_uses_quote(self): + def test_draft_uses_estimate_summary_awaiting_uses_quote(self) -> None: d_job = self._make_job( name="DraftJ", company=self.client_obj, created_dt=_nz_dt(date(2026, 2, 1)) ) @@ -333,7 +333,7 @@ def test_draft_uses_estimate_summary_awaiting_uses_quote(self): rep["pipeline_snapshot"]["awaiting_approval"]["hours_total"], 4.5 ) - def test_narrowed_fetch_preserves_historical_replay(self): + def test_narrowed_fetch_preserves_historical_replay(self) -> None: """A job created long before the reporting window whose transitions leave it in a pipeline stage at ``end_date`` must still surface in the snapshot. Tier 1 narrows the fetch window to save work, so this @@ -364,7 +364,7 @@ def test_narrowed_fetch_preserves_historical_replay(self): self.assertEqual(bucket["count"], 1) self.assertAlmostEqual(bucket["hours_total"], 9.0) - def test_narrowed_fetch_applies_lower_bound_for_in_window_query(self): + def test_narrowed_fetch_applies_lower_bound_for_in_window_query(self) -> None: """The main events query must carry a ``timestamp >=`` filter so we aren't hauling years of history for a short report window. The pre-window query that backfills pipeline-stage jobs is allowed to @@ -411,7 +411,7 @@ def test_narrowed_fetch_applies_lower_bound_for_in_window_query(self): "fetch narrowing regressed. Queries:\n" + "\n".join(jobevent_selects), ) - def test_missing_creation_anchor_excludes_and_warns(self): + def test_missing_creation_anchor_excludes_and_warns(self) -> None: # Build a job and then delete its job_created event. job = self._make_job( name="Anchorless", @@ -438,7 +438,7 @@ def setUp(self) -> None: super().setUp() self.client_obj = self._make_client() - def test_median_p80_sample_size(self): + def test_median_p80_sample_size(self) -> None: """Three approvals in period with created→approved deltas of 5, 10, 20 days.""" for i, gap in enumerate((5, 10, 20)): created = date(2026, 2, 1) @@ -466,7 +466,7 @@ def test_median_p80_sample_size(self): # p80 over [5, 10, 20] (n=3, idx round(0.8*2)=2) = 20 self.assertAlmostEqual(v["p80_days"], 20.0) - def test_pre_window_creation_resolved_for_in_window_approval(self): + def test_pre_window_creation_resolved_for_in_window_approval(self) -> None: """A job created long before the reporting window but approved inside it must have its (pre-window) creation event fetched — the Tier 1 fetch-narrowing regressed this until the relevant-jobs @@ -518,7 +518,7 @@ def test_pre_window_creation_resolved_for_in_window_approval(self): } self.assertEqual(missing_anchor_codes, set()) - def test_missing_creation_anchor_excludes_and_warns(self): + def test_missing_creation_anchor_excludes_and_warns(self) -> None: """A velocity-relevant event in-period on a job missing its job_created anchor must produce a warning, not silent exclusion.""" job = self._make_job( @@ -556,7 +556,7 @@ def setUp(self) -> None: self.start = date(2026, 3, 1) self.end = date(2026, 3, 31) - def test_categorization_is_mutually_exclusive(self): + def test_categorization_is_mutually_exclusive(self) -> None: # Accepted via quote_accepted j_acc = self._make_job( name="Acc", company=self.client_obj, created_dt=_nz_dt(date(2026, 3, 2)) @@ -618,7 +618,7 @@ def test_categorization_is_mutually_exclusive(self): total = sum(f[k]["count"] for k in f) self.assertEqual(total, 5) - def test_missing_creation_anchor_excludes_and_warns(self): + def test_missing_creation_anchor_excludes_and_warns(self) -> None: """A job with events in the reporting period but no usable job_created anchor must produce a funnel warning rather than being silently dropped.""" @@ -652,7 +652,7 @@ def setUp(self) -> None: defaults.daily_approved_hours_target = Decimal("8.00") defaults.save() - def test_rolling_average_derived_from_weekly_series(self): + def test_rolling_average_derived_from_weekly_series(self) -> None: """Build approvals across three weeks; verify the rolling average for the last week equals the mean of the underlying weekly series.""" end_date = date(2026, 3, 22) # Sunday — last week ends here @@ -692,14 +692,14 @@ def test_rolling_average_derived_from_weekly_series(self): sum(approved_series) / 3.0, ) - def test_working_days_match_existing_logic(self): + def test_working_days_match_existing_logic(self) -> None: # 2026-03-02 (Mon) to 2026-03-06 (Fri) = 5 weekdays, no NZ holidays rep = SalesPipelineService.get_report(date(2026, 3, 2), date(2026, 3, 6), 4, 13) self.assertEqual(rep["scoreboard"]["working_days"], 5) class PeriodDefaultTests(SalesPipelineServiceFixturesMixin, BaseTestCase): - def test_no_explicit_dates_reasonable(self): + def test_no_explicit_dates_reasonable(self) -> None: # Even with no jobs, the report should produce a coherent shape rep = SalesPipelineService.get_report( date(2026, 1, 1), timezone.localdate(), 4, 13 diff --git a/apps/accounts/tests/test_auth_observability.py b/apps/accounts/tests/test_auth_observability.py index d17c15ce8..d82cef775 100644 --- a/apps/accounts/tests/test_auth_observability.py +++ b/apps/accounts/tests/test_auth_observability.py @@ -17,7 +17,7 @@ @override_settings(ENABLE_JWT_AUTH=True) -def test_jwt_auth_logs_cookie_miss_with_request_context(): +def test_jwt_auth_logs_cookie_miss_with_request_context() -> None: request = RequestFactory().get( "/api/accounts/me/", HTTP_X_FORWARDED_FOR=f"{TEST_CLIENT_IP}, {TEST_PROXY_IP}", @@ -38,7 +38,7 @@ def test_jwt_auth_logs_cookie_miss_with_request_context(): @override_settings(ENABLE_JWT_AUTH=True) -def test_jwt_auth_does_not_log_cookie_miss_for_xero_webhook(): +def test_jwt_auth_does_not_log_cookie_miss_for_xero_webhook() -> None: request = RequestFactory().post( "/api/xero/webhook/", HTTP_X_FORWARDED_FOR=f"{TEST_WEBHOOK_IP}, {TEST_PROXY_IP}", @@ -99,7 +99,7 @@ def test_current_user_invalid_cookie_remains_an_auth_warning() -> None: @pytest.mark.django_db -def test_logout_logs_cookie_presence_without_token_values(): +def test_logout_logs_cookie_presence_without_token_values() -> None: request = RequestFactory().post( "/api/accounts/logout/", HTTP_X_FORWARDED_FOR=f"{TEST_CLIENT_IP}, {TEST_PROXY_IP}", @@ -120,7 +120,7 @@ def test_logout_logs_cookie_presence_without_token_values(): @pytest.mark.django_db -def test_logout_clears_cookies_even_when_access_cookie_is_invalid(): +def test_logout_clears_cookies_even_when_access_cookie_is_invalid() -> None: client = APIClient() client.cookies["access_token"] = "not-a-valid-jwt" client.cookies["refresh_token"] = "refresh-token-value" diff --git a/apps/accounts/tests/test_displayable_staff.py b/apps/accounts/tests/test_displayable_staff.py index 094d55549..34be2daa1 100644 --- a/apps/accounts/tests/test_displayable_staff.py +++ b/apps/accounts/tests/test_displayable_staff.py @@ -43,7 +43,7 @@ class GetPayrollExcludedStaffIdsTest(BaseTestCase): eligible. """ - def test_excludes_staff_with_null_xero_id(self): + def test_excludes_staff_with_null_xero_id(self) -> None: """A blank Xero ID could leak admin users into payroll exports. The test creates that exact missing-ID shape and requires it in the @@ -52,7 +52,7 @@ def test_excludes_staff_with_null_xero_id(self): admin = _make_staff(email="no-xero@example.com", xero_user_id=None) self.assertIn(str(admin.id), get_payroll_excluded_staff_ids()) - def test_excludes_staff_with_unset_xero_id(self): + def test_excludes_staff_with_unset_xero_id(self) -> None: """Empty strings are another missing-ID shape from forms/imports. This catches code that only checks ``is None`` and would therefore send @@ -61,7 +61,7 @@ def test_excludes_staff_with_unset_xero_id(self): admin = _make_staff(email="empty-xero@example.com", xero_user_id=None) self.assertIn(str(admin.id), get_payroll_excluded_staff_ids()) - def test_excludes_staff_with_non_uuid_xero_id(self): + def test_excludes_staff_with_non_uuid_xero_id(self) -> None: """Malformed IDs must not be treated as payroll enrollment. This catches a broad truthiness check that would let placeholder text @@ -70,7 +70,7 @@ def test_excludes_staff_with_non_uuid_xero_id(self): admin = _make_staff(email="garbage-xero@example.com", xero_user_id="not-a-uuid") self.assertIn(str(admin.id), get_payroll_excluded_staff_ids()) - def test_includes_staff_with_valid_uuid_xero_id(self): + def test_includes_staff_with_valid_uuid_xero_id(self) -> None: """The invalid-ID guard must not exclude real payroll staff. This catches an over-broad exclusion rule by proving a valid Xero UUID @@ -82,7 +82,7 @@ def test_includes_staff_with_valid_uuid_xero_id(self): ) self.assertNotIn(str(employee.id), get_payroll_excluded_staff_ids()) - def test_does_not_depend_on_date_left(self): + def test_does_not_depend_on_date_left(self) -> None: """Payroll exclusion is about Xero identity, not current employment. This catches a refactor that derives the exclusion set only from active @@ -104,7 +104,7 @@ class GetDisplayableStaffTargetDateTest(BaseTestCase): path that must still render. """ - def test_excludes_no_xero_id_staff(self): + def test_excludes_no_xero_id_staff(self) -> None: """Workshop views must not display staff who cannot be paid in Xero. This catches dropping the payroll-enrollment filter while building the @@ -121,7 +121,7 @@ def test_excludes_no_xero_id_staff(self): get_displayable_staff(target_date=target), ) - def test_excludes_staff_who_have_left(self): + def test_excludes_staff_who_have_left(self) -> None: """Departed payroll staff must disappear after their leave date. This catches comparing only join dates, or forgetting the leave-date @@ -138,7 +138,7 @@ def test_excludes_staff_who_have_left(self): get_displayable_staff(target_date=target), ) - def test_includes_active_payroll_enrolled_staff(self): + def test_includes_active_payroll_enrolled_staff(self) -> None: """The exclusion rules must not hide a normal active employee. This catches over-tightening the target-date query by proving an @@ -163,7 +163,7 @@ class GetDisplayableStaffDateRangeTest(BaseTestCase): active on Monday) didn't include them, but the date-range queryset did. """ - def test_no_xero_staff_joining_midweek_is_excluded_from_weekly_range(self): + def test_no_xero_staff_joining_midweek_is_excluded_from_weekly_range(self) -> None: """Mid-week joins can bypass a Monday-only exclusion calculation. This catches that production bug by making the no-Xero staff inactive @@ -183,7 +183,7 @@ def test_no_xero_staff_joining_midweek_is_excluded_from_weekly_range(self): self.assertNotIn(late_admin, result) - def test_no_xero_staff_active_full_range_is_excluded(self): + def test_no_xero_staff_active_full_range_is_excluded(self) -> None: """No-Xero staff must be filtered even when active for the whole week. This catches a range query that only applies employment dates and @@ -199,7 +199,7 @@ def test_no_xero_staff_active_full_range_is_excluded(self): self.assertNotIn(admin, get_displayable_staff(date_range=(monday, sunday))) - def test_left_staff_is_excluded_from_range_after_their_departure(self): + def test_left_staff_is_excluded_from_range_after_their_departure(self) -> None: """A departed employee must not reappear in future weekly views. This catches using only the range start/join date without enforcing @@ -215,7 +215,7 @@ def test_left_staff_is_excluded_from_range_after_their_departure(self): self.assertNotIn(gone, get_displayable_staff(date_range=(monday, sunday))) - def test_payroll_enrolled_staff_active_in_range_is_included(self): + def test_payroll_enrolled_staff_active_in_range_is_included(self) -> None: """The weekly filters must keep legitimate payroll staff visible. This catches an overcorrection for admin leakage that would hide a diff --git a/apps/accounts/tests/test_staff_api.py b/apps/accounts/tests/test_staff_api.py index e143d9ebf..b9fe6d174 100644 --- a/apps/accounts/tests/test_staff_api.py +++ b/apps/accounts/tests/test_staff_api.py @@ -24,7 +24,7 @@ def _png_bytes(size: int = 8) -> bytes: class StaffListCreateAPIViewTests(BaseTestCase): - def test_staff_list_prefetches_groups_for_serializer(self): + def test_staff_list_prefetches_groups_for_serializer(self) -> None: office_user = Staff.objects.create_user( email="office@example.test", password="testpass", diff --git a/apps/company/tests/test_company_invoice_summary.py b/apps/company/tests/test_company_invoice_summary.py index 3ca54c1d9..51e63f239 100644 --- a/apps/company/tests/test_company_invoice_summary.py +++ b/apps/company/tests/test_company_invoice_summary.py @@ -139,7 +139,7 @@ def test_formatting_annotated_companies_does_not_query_invoice_metrics(db): class CompanyCreateInvoiceSummaryTests(BaseTestCase): - def test_create_company_response_formats_annotated_invoice_summary(self): + def test_create_company_response_formats_annotated_invoice_summary(self) -> None: """Create responses must match the company-search summary contract. This catches a view refactor that returns a raw Company payload without @@ -178,7 +178,7 @@ def test_create_company_response_formats_annotated_invoice_summary(self): assert response.data["company"]["last_invoice_date"] is None assert response.data["company"]["total_spend"] == "$0.00" - def test_create_company_cleans_up_local_row_when_xero_create_fails(self): + def test_create_company_cleans_up_local_row_when_xero_create_fails(self) -> None: """Failed Xero contact creation must not leave a half-created company.""" provider = MagicMock() provider.provider_name = "Xero" diff --git a/apps/company/tests/test_get_company_for_xero.py b/apps/company/tests/test_get_company_for_xero.py index 214e36876..9893c2452 100644 --- a/apps/company/tests/test_get_company_for_xero.py +++ b/apps/company/tests/test_get_company_for_xero.py @@ -35,7 +35,7 @@ def _make_company(self, **overrides): ) return company - def test_returns_sdk_contact_instance(self): + def test_returns_sdk_contact_instance(self) -> None: """The payload must be a xero_python Contact, not a dict. If anyone reverts to a snake_case dict, this fails. The SDK's @@ -48,21 +48,21 @@ def test_returns_sdk_contact_instance(self): self.assertIsInstance(payload, Contact) - def test_phones_are_sdk_phone_instances(self): + def test_phones_are_sdk_phone_instances(self) -> None: company = self._make_company(phone="027 351 8326") payload = company.get_company_for_xero() self.assertIsInstance(payload.phones[0], Phone) - def test_addresses_are_sdk_address_instances(self): + def test_addresses_are_sdk_address_instances(self) -> None: company = self._make_company(address="123 Test Street") payload = company.get_company_for_xero() self.assertIsInstance(payload.addresses[0], Address) - def test_populated_company_carries_all_fields(self): + def test_populated_company_carries_all_fields(self) -> None: """Every field a fully-populated Company supplies must reach the Contact.""" company = self._make_company( email="info@acme.test", @@ -82,7 +82,7 @@ def test_populated_company_carries_all_fields(self): self.assertEqual(payload.addresses[0].address_line1, "123 Test Street") self.assertEqual(payload.addresses[0].attention_to, "Acme Ltd") - def test_existing_company_populates_contact_id_on_instance(self): + def test_existing_company_populates_contact_id_on_instance(self) -> None: """contact_id lives on the Contact, not as a caller-side dict mutation. Regression for the dict-mutation pattern at push.py:40 @@ -95,7 +95,7 @@ def test_existing_company_populates_contact_id_on_instance(self): self.assertEqual(payload.contact_id, xero_id) - def test_no_email_emits_none_not_empty_string(self): + def test_no_email_emits_none_not_empty_string(self) -> None: """An unset email must not push an empty string to Xero. Empty string overwrites any operator-typed email Xero already holds @@ -107,21 +107,21 @@ def test_no_email_emits_none_not_empty_string(self): self.assertIsNone(payload.email_address) - def test_no_phone_emits_none_not_empty_string(self): + def test_no_phone_emits_none_not_empty_string(self) -> None: company = self._make_company(phone=None) payload = company.get_company_for_xero() self.assertIsNone(payload.phones[0].phone_number) - def test_no_address_emits_none_not_empty_string(self): + def test_no_address_emits_none_not_empty_string(self) -> None: company = self._make_company(address=None) payload = company.get_company_for_xero() self.assertIsNone(payload.addresses[0].address_line1) - def test_missing_name_raises_value_error(self): + def test_missing_name_raises_value_error(self) -> None: """The name guard must still trip.""" company = self._make_company() company.name = "" @@ -129,7 +129,7 @@ def test_missing_name_raises_value_error(self): with self.assertRaises(ValueError): company.get_company_for_xero() - def test_serialized_wire_format_is_pascalcase(self): + def test_serialized_wire_format_is_pascalcase(self) -> None: """End-to-end wire format check — the bytes Xero would actually receive. The original bug shipped snake_case JSON (`name`, `email_address`, …) diff --git a/apps/job/tests/test_chat_api_endpoints.py b/apps/job/tests/test_chat_api_endpoints.py index 6d2ea4be4..591d81b9b 100644 --- a/apps/job/tests/test_chat_api_endpoints.py +++ b/apps/job/tests/test_chat_api_endpoints.py @@ -24,7 +24,7 @@ class ChatAPIEndpointTests(BaseTestCase): """Test chat API endpoints""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.client_api = APIClient() @@ -76,7 +76,7 @@ def setUp(self): # Authenticate for API requests self.client_api.force_authenticate(user=self.staff) - def test_chat_history_get_empty(self): + def test_chat_history_get_empty(self) -> None: """Test getting empty chat history""" response = self.client_api.get(self.chat_history_url) @@ -84,7 +84,7 @@ def test_chat_history_get_empty(self): self.assertTrue(response.data["success"]) self.assertEqual(response.data["data"]["messages"], []) - def test_chat_history_get_with_messages(self): + def test_chat_history_get_with_messages(self) -> None: """Test getting chat history with existing messages""" JobQuoteChat.objects.create( job=self.job, @@ -112,7 +112,7 @@ def test_chat_history_get_with_messages(self): self.assertEqual(messages[1]["content"], "Hi there!") self.assertEqual(messages[1]["role"], "assistant") - def test_chat_history_post_create_message(self): + def test_chat_history_post_create_message(self) -> None: """Test creating a new chat message""" data = { "message_id": "test-create-msg", @@ -135,7 +135,7 @@ def test_chat_history_post_create_message(self): self.assertEqual(message.content, "Test message creation") self.assertEqual(message.role, "user") - def test_chat_history_post_invalid_data(self): + def test_chat_history_post_invalid_data(self) -> None: """Test creating message with invalid data""" data = { "message_id": "test-invalid-data", @@ -151,7 +151,7 @@ def test_chat_history_post_invalid_data(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - def test_chat_history_delete_message(self): + def test_chat_history_delete_message(self) -> None: """Test deleting a single chat message""" message = JobQuoteChat.objects.create( job=self.job, @@ -172,7 +172,7 @@ def test_chat_history_delete_message(self): # Verify message was deleted self.assertFalse(JobQuoteChat.objects.filter(id=message.id).exists()) - def test_chat_history_delete_all(self): + def test_chat_history_delete_all(self) -> None: """Test deleting all chat messages for a job""" # Create multiple messages JobQuoteChat.objects.create( @@ -207,7 +207,7 @@ def test_chat_history_delete_all(self): # Verify all messages were deleted self.assertEqual(JobQuoteChat.objects.filter(job=self.job).count(), 0) - def test_chat_history_job_not_found(self): + def test_chat_history_job_not_found(self) -> None: """Test accessing chat history for non-existent job""" non_existent_job_id = str(uuid.uuid4()) url = reverse( @@ -253,7 +253,7 @@ def test_chat_interaction_success(self, mock_generate_response): job_id=self.job.id, user_message="Test user message for AI", mode=None ) - def test_chat_interaction_missing_message(self): + def test_chat_interaction_missing_message(self) -> None: """Test chat interaction with missing message""" data = {} @@ -269,7 +269,7 @@ def test_chat_interaction_missing_message(self): "error", response.data ) # Error message returned for invalid input - def test_chat_interaction_empty_message(self): + def test_chat_interaction_empty_message(self) -> None: """Test chat interaction with empty message""" data = { "message": "", @@ -284,7 +284,7 @@ def test_chat_interaction_empty_message(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertFalse(response.data["success"]) - def test_chat_interaction_job_not_found(self): + def test_chat_interaction_job_not_found(self) -> None: """Test chat interaction with non-existent job""" non_existent_job_id = str(uuid.uuid4()) url = reverse( @@ -345,7 +345,7 @@ def test_chat_interaction_internal_error(self, mock_generate_response): class ChatAPIPermissionTests(BaseTestCase): """Test API permissions and authentication""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.client_api = APIClient() @@ -396,7 +396,7 @@ def setUp(self): "jobs:job_quote_chat_interaction", kwargs={"job_id": str(self.job.id)} ) - def test_unauthenticated_access(self): + def test_unauthenticated_access(self) -> None: """Test unauthenticated access to chat endpoints""" # Test chat history endpoint response = self.client_api.get(self.chat_history_url) @@ -410,7 +410,7 @@ def test_unauthenticated_access(self): ) self.assertIn(response.status_code, [200, 401, 403]) - def test_authenticated_access(self): + def test_authenticated_access(self) -> None: """Test authenticated access to chat endpoints""" self.client_api.force_authenticate(user=self.staff) @@ -418,7 +418,7 @@ def test_authenticated_access(self): response = self.client_api.get(self.chat_history_url) self.assertEqual(response.status_code, status.HTTP_200_OK) - def test_admin_access(self): + def test_admin_access(self) -> None: """Test admin access to chat endpoints""" self.client_api.force_authenticate(user=self.admin_staff) @@ -430,7 +430,7 @@ def test_admin_access(self): class ChatAPIValidationTests(BaseTestCase): """Test API data validation""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.client_api = APIClient() @@ -469,7 +469,7 @@ def setUp(self): ) self.client_api.force_authenticate(user=self.staff) - def test_create_message_valid_roles(self): + def test_create_message_valid_roles(self) -> None: """Test creating messages with valid roles""" valid_roles = ["user", "assistant"] @@ -489,7 +489,7 @@ def test_create_message_valid_roles(self): self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.data["data"]["role"], role) - def test_create_message_invalid_role(self): + def test_create_message_invalid_role(self) -> None: """Test creating message with invalid role""" data = { "message_id": "test-invalid-role", @@ -505,7 +505,7 @@ def test_create_message_invalid_role(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - def test_create_message_missing_content(self): + def test_create_message_missing_content(self) -> None: """Test creating message with missing content""" data = { "message_id": "test-missing-content", @@ -520,7 +520,7 @@ def test_create_message_missing_content(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - def test_create_message_empty_content(self): + def test_create_message_empty_content(self) -> None: """Test creating message with empty content""" data = { "message_id": "test-empty-content", @@ -536,7 +536,7 @@ def test_create_message_empty_content(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - def test_create_message_with_metadata(self): + def test_create_message_with_metadata(self) -> None: """Test creating message with metadata""" data = { "message_id": "test-with-metadata", @@ -561,7 +561,7 @@ def test_create_message_with_metadata(self): response.data["data"]["metadata"]["custom_field"], "test_value" ) - def test_nonexistent_job_id(self): + def test_nonexistent_job_id(self) -> None: """Test API with non-existent job ID""" # Use a valid UUID format that doesn't exist in the database nonexistent_url = reverse( diff --git a/apps/job/tests/test_chat_performance.py b/apps/job/tests/test_chat_performance.py index c33313137..c74875bc0 100644 --- a/apps/job/tests/test_chat_performance.py +++ b/apps/job/tests/test_chat_performance.py @@ -44,7 +44,7 @@ def create_text_response(content: str) -> Mock: class ChatQueryOptimizationTests(BaseTestCase): """Test chat database query counts and bulk operations""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.company_defaults = CompanyDefaults.get_solo() @@ -76,7 +76,7 @@ def setUp(self): self.service = ChatService() - def test_database_query_optimization(self): + def test_database_query_optimization(self) -> None: """Test database query optimization""" # Create conversation history for i in range(50): @@ -110,7 +110,7 @@ def test_database_query_optimization(self): f"Expected <=7 queries, got {len(ctx.captured_queries)}", ) - def test_bulk_message_creation(self): + def test_bulk_message_creation(self) -> None: """Test bulk database message creation""" jobs = [] for i in range(3): diff --git a/apps/job/tests/test_chat_service.py b/apps/job/tests/test_chat_service.py index dfddf2288..264fcd895 100644 --- a/apps/job/tests/test_chat_service.py +++ b/apps/job/tests/test_chat_service.py @@ -118,7 +118,7 @@ def create_mock_llm(model_name: str = "test-model") -> Mock: class ChatServiceConfigurationTests(BaseTestCase): """Test service configuration and initialization""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.company_defaults = CompanyDefaults.get_solo() @@ -143,14 +143,14 @@ def setUp(self): self.service = ChatService() - def test_service_initialization(self): + def test_service_initialization(self) -> None: """Test service initializes with required components""" self.assertIsNotNone(self.service.quoting_tool) self.assertIsNotNone(self.service.query_tool) self.assertIsNotNone(self.service.mode_controller) self.assertIsNotNone(self.service.file_service) - def test_llm_service_no_provider(self): + def test_llm_service_no_provider(self) -> None: """Test LLM service creation fails when no AI provider configured""" # Remove all AI providers AIProvider.objects.all().delete() @@ -160,7 +160,7 @@ def test_llm_service_no_provider(self): self.assertIn("No AI provider configured", str(context.exception)) - def test_llm_service_no_api_key(self): + def test_llm_service_no_api_key(self) -> None: """Test LLM service creation fails when provider has no API key""" AIProvider.objects.all().delete() AIProvider.objects.create( @@ -175,7 +175,7 @@ def test_llm_service_no_api_key(self): self.assertIn("missing an API key", str(context.exception)) - def test_llm_service_no_model_name(self): + def test_llm_service_no_model_name(self) -> None: """Test LLM service creation fails when provider has no model name""" AIProvider.objects.all().delete() AIProvider.objects.create( @@ -190,7 +190,7 @@ def test_llm_service_no_model_name(self): self.assertIn("missing a model name", str(context.exception)) - def test_system_prompt_generation(self): + def test_system_prompt_generation(self) -> None: """Test system prompt includes job context""" prompt = self.service._get_system_prompt(self.job) @@ -200,7 +200,7 @@ def test_system_prompt_generation(self): self.assertIn(self.company.name, prompt) self.assertIn(self.job.description, prompt) - def test_mcp_tools_definition(self): + def test_mcp_tools_definition(self) -> None: """Test MCP tools are properly defined in OpenAI format""" tools = self.service._get_mcp_tools() @@ -228,7 +228,7 @@ def test_mcp_tools_definition(self): for expected_tool in expected_tools: self.assertIn(expected_tool, tool_names) - def test_role_conversion(self): + def test_role_conversion(self) -> None: """Test database role to OpenAI role conversion""" # Both 'user' and 'assistant' should map to themselves self.assertEqual(ChatService._to_openai_role("user"), "user") @@ -238,18 +238,18 @@ def test_role_conversion(self): class ChatServiceToolExecutionTests(TestCase): """Test MCP tool execution""" - def setUp(self): + def setUp(self) -> None: self.service = ChatService() # Create a mock for the quoting_tool instance attribute self.mock_quoting_tool = Mock() self.service.quoting_tool = self.mock_quoting_tool - def test_execute_unknown_tool(self): + def test_execute_unknown_tool(self) -> None: """Test execution of unknown tool""" result = self.service._execute_mcp_tool("unknown_tool", {}) self.assertEqual(result, "Unknown tool: unknown_tool") - def test_execute_tool_with_exception(self): + def test_execute_tool_with_exception(self) -> None: """Test tool execution with exception""" self.mock_quoting_tool.search_products.side_effect = Exception("Tool error") @@ -262,7 +262,7 @@ def test_execute_tool_with_exception(self): class ChatServiceResponseGenerationTests(BaseTestCase): """Test AI response generation with database transactions""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.company_defaults = CompanyDefaults.get_solo() @@ -294,7 +294,7 @@ def setUp(self): self.service = ChatService() - def test_job_not_found(self): + def test_job_not_found(self) -> None: """Test response generation with non-existent job""" non_existent_job_id = str(uuid.uuid4()) @@ -412,7 +412,7 @@ def test_generate_response_error_handling(self, mock_get_llm): class ChatServiceMultimodalTests(BaseTestCase): """Test multimodal content handling""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.company_defaults = CompanyDefaults.get_solo() @@ -436,7 +436,7 @@ def setUp(self): self.service = ChatService() - def test_build_multimodal_content_no_files(self): + def test_build_multimodal_content_no_files(self) -> None: """Test _build_multimodal_content returns text when no files""" mock_llm = MockLLMResponseBuilder.create_mock_llm() mock_llm.supports_vision.return_value = True @@ -445,7 +445,7 @@ def test_build_multimodal_content_no_files(self): self.assertEqual(result, "Test message") - def test_build_multimodal_content_no_vision_support(self): + def test_build_multimodal_content_no_vision_support(self) -> None: """Test _build_multimodal_content falls back to text reference""" mock_llm = MockLLMResponseBuilder.create_mock_llm() mock_llm.supports_vision.return_value = False @@ -461,7 +461,7 @@ def test_build_multimodal_content_no_vision_support(self): self.assertIn("Test message", result) self.assertIn("[Attached files: test.png]", result) - def test_build_multimodal_content_file_not_found(self): + def test_build_multimodal_content_file_not_found(self) -> None: """Test _build_multimodal_content handles missing files""" mock_llm = MockLLMResponseBuilder.create_mock_llm() mock_llm.supports_vision.return_value = True @@ -482,7 +482,7 @@ def test_build_multimodal_content_file_not_found(self): text_content = " ".join(p["text"] for p in text_parts) self.assertIn("not found", text_content) - def test_build_multimodal_content_with_image(self): + def test_build_multimodal_content_with_image(self) -> None: """Test _build_multimodal_content with image file""" mock_llm = MockLLMResponseBuilder.create_mock_llm() mock_llm.supports_vision.return_value = True @@ -584,7 +584,7 @@ def test_build_multimodal_content_with_image(self): finally: os.unlink(temp_path) - def test_build_multimodal_content_unsupported_file_type(self): + def test_build_multimodal_content_unsupported_file_type(self) -> None: """Test _build_multimodal_content with unsupported file type""" mock_llm = MockLLMResponseBuilder.create_mock_llm() mock_llm.supports_vision.return_value = True @@ -611,7 +611,7 @@ def test_build_multimodal_content_unsupported_file_type(self): class ChatServiceIntegrationTests(BaseTestCase): """Integration tests for the complete chat flow""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.company_defaults = CompanyDefaults.get_solo() @@ -669,7 +669,7 @@ def test_complete_chat_flow(self, mock_get_llm): self.assertIn("user_message", saved_message.metadata) self.assertIn("tool_definitions", saved_message.metadata) - def test_conversation_persistence(self): + def test_conversation_persistence(self) -> None: """Test that conversation history is properly maintained""" # Create a sequence of messages messages = [ @@ -699,7 +699,7 @@ def test_conversation_persistence(self): class ChatServiceModeResponseTests(BaseTestCase): """Test mode-based response generation""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.company_defaults = CompanyDefaults.get_solo() diff --git a/apps/job/tests/test_event_deduplication.py b/apps/job/tests/test_event_deduplication.py index 80231d499..b47865630 100644 --- a/apps/job/tests/test_event_deduplication.py +++ b/apps/job/tests/test_event_deduplication.py @@ -19,7 +19,7 @@ class EventDeduplicationTest(BaseTestCase): These tests catch both duplicate leakage and over-broad deduplication. """ - def setUp(self): + def setUp(self) -> None: self.user = Staff.objects.create_user( email="test@example.com", password="testpass123", @@ -41,7 +41,7 @@ def setUp(self): staff=self.test_staff, ) - def test_model_prevents_duplicate_manual_events(self): + def test_model_prevents_duplicate_manual_events(self) -> None: """Direct model writes must not bypass manual-note duplicate guards. This catches imports/admin paths that create ``JobEvent`` rows without @@ -63,7 +63,7 @@ def test_model_prevents_duplicate_manual_events(self): event_type="manual_note", ) - def test_create_safe_method_prevents_duplicates(self): + def test_create_safe_method_prevents_duplicates(self) -> None: """Retry-safe creation must return the existing note, not error or duplicate. This catches callers that use ``create_safe`` during retry flows and @@ -86,7 +86,7 @@ def test_create_safe_method_prevents_duplicates(self): self.assertFalse(created2) self.assertEqual(event1.id, event2.id) - def test_service_prevents_duplicate_events(self): + def test_service_prevents_duplicate_events(self) -> None: """The REST service must collapse immediate duplicate submissions. This catches frontend retry/double-click regressions by going through @@ -122,7 +122,7 @@ def test_service_prevents_duplicate_events(self): ) self.assertEqual(events.count(), 1) - def test_different_users_can_create_same_event(self): + def test_different_users_can_create_same_event(self) -> None: """Deduplication must not erase another staff member's identical note. This catches over-broad dedup identity that keys only on job and note @@ -161,7 +161,7 @@ def test_different_users_can_create_same_event(self): ) self.assertEqual(events.count(), 2) - def test_automatic_events_not_affected(self): + def test_automatic_events_not_affected(self) -> None: """Automatic audit events must not be collapsed like manual notes. This catches a dedup refactor that applies manual-note rules to status @@ -187,7 +187,9 @@ def test_automatic_events_not_affected(self): events = JobEvent.objects.filter(job=self.job, event_type="status_changed") self.assertEqual(events.count(), 3) - def test_manual_note_dedup_identity_normalises_text_only_within_same_user(self): + def test_manual_note_dedup_identity_normalises_text_only_within_same_user( + self, + ) -> None: """Manual note identity should ignore text case/spacing but keep staff. This catches two plausible mistakes: failing to collapse harmless text diff --git a/apps/job/tests/test_job_event_tracking.py b/apps/job/tests/test_job_event_tracking.py index c632d7320..2a813cf9b 100644 --- a/apps/job/tests/test_job_event_tracking.py +++ b/apps/job/tests/test_job_event_tracking.py @@ -25,7 +25,7 @@ class JobEventTrackingTest(BaseTestCase): """Verify that Job.save() creates events for tracked field changes.""" - def setUp(self): + def setUp(self) -> None: self.user = Staff.objects.create_user( email="tracker@example.com", password="testpass123", @@ -46,7 +46,7 @@ def setUp(self): ) self.job.save(staff=self.user) - def test_status_change_creates_event(self): + def test_status_change_creates_event(self) -> None: self.job.status = "in_progress" self.job.save(staff=self.user) @@ -58,7 +58,7 @@ def test_status_change_creates_event(self): self.assertEqual(event.delta_before["status"], "draft") self.assertEqual(event.delta_after["status"], "in_progress") - def test_event_list_serializes_staff(self): + def test_event_list_serializes_staff(self) -> None: JobEvent.objects.create( job=self.job, staff=self.user, @@ -73,7 +73,7 @@ def test_event_list_serializes_staff(self): self.assertEqual(response.status_code, 200) self.assertEqual(response.data["events"][0]["staff"], "Test Tracker") - def test_status_change_to_archived_clears_assigned_staff(self): + def test_status_change_to_archived_clears_assigned_staff(self) -> None: assigned_staff = Staff.objects.create_user( email="assigned@example.com", password="testpass123", @@ -87,7 +87,7 @@ def test_status_change_to_archived_clears_assigned_staff(self): self.assertFalse(self.job.people.exists()) - def test_name_change_creates_event(self): + def test_name_change_creates_event(self) -> None: self.job.name = "Renamed Job" self.job.save(staff=self.user) @@ -100,13 +100,13 @@ def test_name_change_creates_event(self): self.assertIn("name", event.delta_before) self.assertEqual(event.delta_after["name"], "Renamed Job") - def test_no_change_creates_no_event(self): + def test_no_change_creates_no_event(self) -> None: count_before = JobEvent.objects.filter(job=self.job).count() self.job.save(staff=self.user) count_after = JobEvent.objects.filter(job=self.job).count() self.assertEqual(count_before, count_after) - def test_multiple_field_changes_create_single_event(self): + def test_multiple_field_changes_create_single_event(self) -> None: count_before = JobEvent.objects.filter(job=self.job).count() self.job.name = "New Name" self.job.order_number = "PO-999" @@ -118,14 +118,14 @@ def test_multiple_field_changes_create_single_event(self): self.assertIn("name", event.delta_before) self.assertIn("order_number", event.delta_before) - def test_untracked_field_change_creates_no_event(self): + def test_untracked_field_change_creates_no_event(self) -> None: count_before = JobEvent.objects.filter(job=self.job).count() self.job.fully_invoiced = True self.job.save(staff=self.user) count_after = JobEvent.objects.filter(job=self.job).count() self.assertEqual(count_before, count_after) - def test_enrichment_kwargs_passed_to_event(self): + def test_enrichment_kwargs_passed_to_event(self) -> None: import uuid cid = uuid.uuid4() @@ -144,14 +144,14 @@ def test_enrichment_kwargs_passed_to_event(self): self.assertEqual(event.delta_meta, {"fields": ["name"]}) self.assertEqual(event.delta_checksum, "abc123") - def test_event_type_override(self): + def test_event_type_override(self) -> None: self.job.status = "approved" self.job.save(staff=self.user, event_type_override="quote_accepted") event = JobEvent.objects.filter(job=self.job).order_by("-timestamp").first() self.assertEqual(event.event_type, "quote_accepted") - def test_status_transition_to_completed_persists_completed_at(self): + def test_status_transition_to_completed_persists_completed_at(self) -> None: self.assertIsNone(self.job.completed_at) self.job.status = "recently_completed" @@ -161,7 +161,7 @@ def test_status_transition_to_completed_persists_completed_at(self): self.assertEqual(self.job.status, "recently_completed") self.assertIsNotNone(self.job.completed_at) - def test_status_revert_clears_completed_at(self): + def test_status_revert_clears_completed_at(self) -> None: self.job.status = "recently_completed" self.job.save(staff=self.user) self.job.refresh_from_db() @@ -173,7 +173,7 @@ def test_status_revert_clears_completed_at(self): self.job.refresh_from_db() self.assertIsNone(self.job.completed_at) - def test_accepted_for_work_at_returns_first_approved_event(self): + def test_accepted_for_work_at_returns_first_approved_event(self) -> None: first = timezone.now() - timedelta(days=3) second = timezone.now() - timedelta(days=1) JobEvent.objects.create( @@ -193,7 +193,9 @@ def test_accepted_for_work_at_returns_first_approved_event(self): self.assertEqual(self.job.accepted_for_work_at, first) - def test_accepted_for_work_at_uses_in_progress_if_approved_was_skipped(self): + def test_accepted_for_work_at_uses_in_progress_if_approved_was_skipped( + self, + ) -> None: accepted = timezone.now() - timedelta(days=2) JobEvent.objects.create( job=self.job, @@ -205,7 +207,7 @@ def test_accepted_for_work_at_uses_in_progress_if_approved_was_skipped(self): self.assertEqual(self.job.accepted_for_work_at, accepted) - def test_accepted_for_work_at_prefers_approved_over_later_in_progress(self): + def test_accepted_for_work_at_prefers_approved_over_later_in_progress(self) -> None: approved = timezone.now() - timedelta(days=4) in_progress = timezone.now() - timedelta(days=1) JobEvent.objects.create( @@ -227,12 +229,14 @@ def test_accepted_for_work_at_prefers_approved_over_later_in_progress(self): def test_accepted_for_work_at_ignores_quote_acceptance_date_without_status_event( self, - ): + ) -> None: self.job.quote_acceptance_date = timezone.now() - timedelta(days=5) self.assertIsNone(self.job.accepted_for_work_at) - def test_accepted_for_work_at_uses_approved_status_from_quote_accepted_event(self): + def test_accepted_for_work_at_uses_approved_status_from_quote_accepted_event( + self, + ) -> None: accepted = timezone.now() - timedelta(days=3) JobEvent.objects.create( job=self.job, @@ -244,7 +248,7 @@ def test_accepted_for_work_at_uses_approved_status_from_quote_accepted_event(sel self.assertEqual(self.job.accepted_for_work_at, accepted) - def test_status_change_with_update_fields_persists_completed_at(self): + def test_status_change_with_update_fields_persists_completed_at(self) -> None: self.assertIsNone(self.job.completed_at) self.job.status = "recently_completed" @@ -261,22 +265,22 @@ class JobEventDescriptionTest(SimpleTestCase): def _event(self, event_type, detail): return JobEvent(event_type=event_type, detail=detail) - def test_description_property_delegates_to_build_description(self): + def test_description_property_delegates_to_build_description(self) -> None: event = self._event("manual_note", {"note_text": "A scribbled note"}) self.assertEqual(event.description, "A scribbled note") self.assertEqual(event.description, event.build_description()) - def test_legacy_description_takes_precedence(self): + def test_legacy_description_takes_precedence(self) -> None: event = self._event( "job_updated", {"legacy_description": "Old free-text", "changes": []} ) self.assertEqual(event.description, "Old free-text") - def test_unknown_event_type_returns_sentinel(self): + def test_unknown_event_type_returns_sentinel(self) -> None: event = self._event("never_seen_event_type", {}) self.assertEqual(event.description, "(never_seen_event_type)") - def test_friendly_boolean_rejected_set(self): + def test_friendly_boolean_rejected_set(self) -> None: event = self._event( "job_rejected", { @@ -287,7 +291,7 @@ def test_friendly_boolean_rejected_set(self): ) self.assertEqual(event.description, "Job marked as rejected") - def test_friendly_boolean_rejected_cleared(self): + def test_friendly_boolean_rejected_cleared(self) -> None: event = self._event( "job_updated", { @@ -298,7 +302,7 @@ def test_friendly_boolean_rejected_cleared(self): ) self.assertEqual(event.description, "Rejection cleared") - def test_friendly_boolean_complex_job(self): + def test_friendly_boolean_complex_job(self) -> None: event = self._event( "job_updated", { @@ -309,7 +313,7 @@ def test_friendly_boolean_complex_job(self): ) self.assertEqual(event.description, "Marked as complex job") - def test_friendly_boolean_paid(self): + def test_friendly_boolean_paid(self) -> None: event = self._event( "payment_received", { @@ -320,7 +324,7 @@ def test_friendly_boolean_paid(self): ) self.assertEqual(event.description, "Marked as paid") - def test_friendly_boolean_collected(self): + def test_friendly_boolean_collected(self) -> None: event = self._event( "job_collected", { @@ -331,7 +335,7 @@ def test_friendly_boolean_collected(self): ) self.assertEqual(event.description, "Marked as collected") - def test_long_text_field_truncates(self): + def test_long_text_field_truncates(self) -> None: long_value = "x" * 200 event = self._event( "job_updated", @@ -350,7 +354,7 @@ def test_long_text_field_truncates(self): # Truncated value should be much shorter than the original self.assertLess(len(rendered), len(long_value) + 50) - def test_default_descriptor_for_unknown_field(self): + def test_default_descriptor_for_unknown_field(self) -> None: event = self._event( "job_updated", { @@ -361,7 +365,7 @@ def test_default_descriptor_for_unknown_field(self): ) self.assertEqual(event.description, "Some field changed from 'A' to 'B'") - def test_multiple_changes_join_with_period(self): + def test_multiple_changes_join_with_period(self) -> None: event = self._event( "job_updated", { @@ -380,7 +384,7 @@ def test_multiple_changes_join_with_period(self): "Marked as paid. Order number changed from 'PO-1' to 'PO-2'", ) - def test_priority_changed_within_column(self): + def test_priority_changed_within_column(self) -> None: event = self._event( "priority_changed", { @@ -406,7 +410,7 @@ def test_priority_changed_within_column(self): "Priority increased from 11th to 5th of 51 in In Progress", ) - def test_priority_changed_within_column_decreased(self): + def test_priority_changed_within_column_decreased(self) -> None: event = self._event( "priority_changed", { @@ -432,7 +436,7 @@ def test_priority_changed_within_column_decreased(self): "Priority decreased from 5th to 11th of 51 in In Progress", ) - def test_priority_changed_cross_column(self): + def test_priority_changed_cross_column(self) -> None: event = self._event( "priority_changed", { @@ -458,7 +462,7 @@ def test_priority_changed_cross_column(self): "Moved from In Progress (11th of 51) to Quoting (3rd of 27)", ) - def test_priority_legacy_float_diff_increased(self): + def test_priority_legacy_float_diff_increased(self) -> None: event = self._event( "priority_changed", { @@ -473,7 +477,7 @@ def test_priority_legacy_float_diff_increased(self): ) self.assertEqual(event.description, "Priority increased") - def test_priority_legacy_float_diff_decreased(self): + def test_priority_legacy_float_diff_decreased(self) -> None: event = self._event( "priority_changed", { @@ -488,7 +492,7 @@ def test_priority_legacy_float_diff_decreased(self): ) self.assertEqual(event.description, "Priority decreased") - def test_priority_legacy_unparseable_floats_returns_safe_text(self): + def test_priority_legacy_unparseable_floats_returns_safe_text(self) -> None: event = self._event( "priority_changed", { @@ -499,13 +503,13 @@ def test_priority_legacy_unparseable_floats_returns_safe_text(self): ) self.assertEqual(event.description, "Priority changed") - def test_helper_truncate_short_text_unchanged(self): + def test_helper_truncate_short_text_unchanged(self) -> None: self.assertEqual(_truncate("hello"), "hello") - def test_helper_truncate_long_text(self): + def test_helper_truncate_long_text(self) -> None: self.assertEqual(_truncate("a" * 100, 10), "aaaaaaaaa…") - def test_helper_format_ordinal(self): + def test_helper_format_ordinal(self) -> None: self.assertEqual(_format_ordinal(1), "1st") self.assertEqual(_format_ordinal(2), "2nd") self.assertEqual(_format_ordinal(3), "3rd") @@ -516,7 +520,7 @@ def test_helper_format_ordinal(self): self.assertEqual(_format_ordinal(21), "21st") self.assertEqual(_format_ordinal(22), "22nd") - def test_helper_truthy(self): + def test_helper_truthy(self) -> None: self.assertTrue(_truthy(True)) self.assertTrue(_truthy("Yes")) self.assertTrue(_truthy("yes")) @@ -530,7 +534,7 @@ def test_helper_truthy(self): class PriorityPositionCaptureTest(BaseTestCase): """Verify KanbanService.reorder_job attaches detail.position to the JobEvent.""" - def setUp(self): + def setUp(self) -> None: self.user = Staff.objects.create_user( email="kanban@example.com", password="testpass123", @@ -555,7 +559,7 @@ def _make_job(self, name, status="in_progress"): job.save(staff=self.user) return job - def test_within_column_drag_records_position(self): + def test_within_column_drag_records_position(self) -> None: from apps.job.services.kanban_service import KanbanService job_a = self._make_job("Job A") @@ -585,7 +589,7 @@ def test_within_column_drag_records_position(self): self.assertEqual(position["old_position"], 3) # was at the bottom self.assertEqual(position["new_position"], 1) # now at the top - def test_noop_priority_change_creates_no_event(self): + def test_noop_priority_change_creates_no_event(self) -> None: """When priority_position has equal old/new positions, no JobEvent is created.""" job = self._make_job("Solo") before_count = JobEvent.objects.filter( @@ -612,7 +616,7 @@ def test_noop_priority_change_creates_no_event(self): ).count() self.assertEqual(after_count, before_count) - def test_cross_column_drag_records_old_and_new_totals(self): + def test_cross_column_drag_records_old_and_new_totals(self) -> None: from apps.job.services.kanban_service import KanbanService in_progress_job = self._make_job("Mover", status="in_progress") diff --git a/apps/job/tests/test_job_files_api.py b/apps/job/tests/test_job_files_api.py index 6a5af452b..5e11c51ea 100644 --- a/apps/job/tests/test_job_files_api.py +++ b/apps/job/tests/test_job_files_api.py @@ -18,7 +18,7 @@ class JobFilesApiTests(BaseAPITestCase): upload, find, or download job files. """ - def setUp(self): + def setUp(self) -> None: super().setUp() self._tmp_dropbox = tempfile.mkdtemp(prefix="dw-job-files-api-test-") self._settings_override = override_settings( @@ -46,12 +46,14 @@ def setUp(self): self.api = APIClient() self.api.force_authenticate(user=self.office_staff) - def tearDown(self): + def tearDown(self) -> None: self._settings_override.disable() shutil.rmtree(self._tmp_dropbox, ignore_errors=True) super().tearDown() - def test_upload_returns_full_job_file_and_file_is_immediately_available(self): + def test_upload_returns_full_job_file_and_file_is_immediately_available( + self, + ) -> None: payload = b"job attachment contents" file_obj = SimpleUploadedFile( "attachment.txt", @@ -82,7 +84,7 @@ def test_upload_returns_full_job_file_and_file_is_immediately_available(self): self.assertEqual(download_response.status_code, 200) self.assertEqual(b"".join(download_response.streaming_content), payload) - def test_upload_accepts_twenty_megabyte_attachment(self): + def test_upload_accepts_twenty_megabyte_attachment(self) -> None: payload = b"7" * (20 * 1024 * 1024) file_obj = SimpleUploadedFile( "large-attachment.txt", diff --git a/apps/job/tests/test_job_invoicing.py b/apps/job/tests/test_job_invoicing.py index 55ddae0b8..93430193d 100644 --- a/apps/job/tests/test_job_invoicing.py +++ b/apps/job/tests/test_job_invoicing.py @@ -17,7 +17,7 @@ class TestRecalculateJobInvoicingState(BaseTestCase): """Tests for recalculate_job_invoicing_state().""" - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Test Company", xero_last_modified=timezone.now(), @@ -64,7 +64,7 @@ def _create_invoice(self, job, amount, status="AUTHORISED"): # --- T&M tests --- - def test_tm_fully_invoiced_when_invoiced_equals_actual(self): + def test_tm_fully_invoiced_when_invoiced_equals_actual(self) -> None: """T&M job is fully invoiced when invoiced amount equals actual revenue.""" job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("1000.00")) @@ -75,7 +75,7 @@ def test_tm_fully_invoiced_when_invoiced_equals_actual(self): job.refresh_from_db() self.assertTrue(job.fully_invoiced) - def test_tm_fully_invoiced_when_invoiced_exceeds_actual(self): + def test_tm_fully_invoiced_when_invoiced_exceeds_actual(self) -> None: """T&M job is fully invoiced when invoiced amount exceeds actual revenue.""" job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("1000.00")) @@ -86,7 +86,7 @@ def test_tm_fully_invoiced_when_invoiced_exceeds_actual(self): job.refresh_from_db() self.assertTrue(job.fully_invoiced) - def test_tm_not_fully_invoiced_when_invoiced_less_than_actual(self): + def test_tm_not_fully_invoiced_when_invoiced_less_than_actual(self) -> None: """T&M job is not fully invoiced when invoiced less than actual revenue.""" job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("1000.00")) @@ -99,7 +99,7 @@ def test_tm_not_fully_invoiced_when_invoiced_less_than_actual(self): # --- Fixed-price tests --- - def test_fixed_price_fully_invoiced_when_invoiced_equals_quote(self): + def test_fixed_price_fully_invoiced_when_invoiced_equals_quote(self) -> None: """Fixed-price job is fully invoiced when invoiced matches quote revenue.""" job = self._create_job("fixed_price") self._add_revenue_line(job.latest_actual, Decimal("800.00")) @@ -111,7 +111,7 @@ def test_fixed_price_fully_invoiced_when_invoiced_equals_quote(self): job.refresh_from_db() self.assertTrue(job.fully_invoiced) - def test_fixed_price_not_fully_invoiced_even_if_exceeds_actual(self): + def test_fixed_price_not_fully_invoiced_even_if_exceeds_actual(self) -> None: """Fixed-price job is NOT fully invoiced when invoiced >= actual but < quote.""" job = self._create_job("fixed_price") self._add_revenue_line(job.latest_actual, Decimal("800.00")) @@ -127,7 +127,7 @@ def test_fixed_price_not_fully_invoiced_even_if_exceeds_actual(self): # --- Edge cases --- - def test_not_fully_invoiced_with_no_invoices(self): + def test_not_fully_invoiced_with_no_invoices(self) -> None: """Job with no invoices is not fully invoiced.""" job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("1000.00")) @@ -137,7 +137,7 @@ def test_not_fully_invoiced_with_no_invoices(self): job.refresh_from_db() self.assertFalse(job.fully_invoiced) - def test_voided_invoices_excluded(self): + def test_voided_invoices_excluded(self) -> None: """Voided invoices should not count toward total invoiced.""" job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("1000.00")) @@ -148,7 +148,7 @@ def test_voided_invoices_excluded(self): job.refresh_from_db() self.assertFalse(job.fully_invoiced) - def test_deleted_invoices_excluded(self): + def test_deleted_invoices_excluded(self) -> None: """Deleted invoices should not count toward total invoiced.""" job = self._create_job("time_materials") self._add_revenue_line(job.latest_actual, Decimal("1000.00")) diff --git a/apps/job/tests/test_job_latest_costsets.py b/apps/job/tests/test_job_latest_costsets.py index 35fbb2c89..78066268c 100644 --- a/apps/job/tests/test_job_latest_costsets.py +++ b/apps/job/tests/test_job_latest_costsets.py @@ -9,7 +9,7 @@ class JobLatestCostSetCreationTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Latest CostSet Company", xero_last_modified="2024-01-01T00:00:00Z", @@ -34,7 +34,7 @@ def _assert_initial_cost_sets(self, job: Job) -> None: self.assertEqual(job.cost_sets.filter(kind="quote").count(), 1) self.assertEqual(job.cost_sets.filter(kind="actual").count(), 1) - def test_manager_create_seeds_required_latest_cost_sets(self): + def test_manager_create_seeds_required_latest_cost_sets(self) -> None: job = Job.objects.create( company=self.client_obj, name="Manager create job", @@ -43,7 +43,7 @@ def test_manager_create_seeds_required_latest_cost_sets(self): self._assert_initial_cost_sets(job) - def test_model_save_seeds_required_latest_cost_sets(self): + def test_model_save_seeds_required_latest_cost_sets(self) -> None: job = Job(company=self.client_obj, name="Model save job") job.save(staff=self.test_staff) @@ -51,7 +51,7 @@ def test_model_save_seeds_required_latest_cost_sets(self): class JobLatestCostSetDeletionTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Latest CostSet Deletion Company", xero_last_modified="2024-01-01T00:00:00Z", @@ -62,13 +62,13 @@ def setUp(self): staff=self.test_staff, ) - def test_latest_cost_set_cannot_be_deleted_directly(self): + def test_latest_cost_set_cannot_be_deleted_directly(self) -> None: with self.assertRaises(RestrictedError): self.job.latest_quote.delete() self.assertTrue(CostSet.objects.filter(id=self.job.latest_quote_id).exists()) - def test_deleting_job_cascades_cost_sets(self): + def test_deleting_job_cascades_cost_sets(self) -> None: cost_set_ids = list(self.job.cost_sets.values_list("id", flat=True)) self.job.delete() diff --git a/apps/job/tests/test_job_rest_service.py b/apps/job/tests/test_job_rest_service.py index 2d76e840f..44e4bf4dd 100644 --- a/apps/job/tests/test_job_rest_service.py +++ b/apps/job/tests/test_job_rest_service.py @@ -13,7 +13,9 @@ class JobRestServiceCreateJobTests(BaseTestCase): - def test_fixed_price_create_copies_estimate_pay_item_without_relation_loads(self): + def test_fixed_price_create_copies_estimate_pay_item_without_relation_loads( + self, + ) -> None: company = Company.objects.create( name="Create Job Company", xero_last_modified=timezone.now(), @@ -46,7 +48,7 @@ def test_fixed_price_create_copies_estimate_pay_item_without_relation_loads(self class JobRestServiceEditTests(BaseTestCase): - def test_get_job_for_edit_serializes_event_staff(self): + def test_get_job_for_edit_serializes_event_staff(self) -> None: company = Company.objects.create( name="Edit Job Company", xero_last_modified=timezone.now(), diff --git a/apps/job/tests/test_kanban_reorder_priority.py b/apps/job/tests/test_kanban_reorder_priority.py index 9dc1b1a3d..1fb2f89c4 100644 --- a/apps/job/tests/test_kanban_reorder_priority.py +++ b/apps/job/tests/test_kanban_reorder_priority.py @@ -12,7 +12,7 @@ class KanbanReorderPriorityTest(BaseTestCase): - def setUp(self): + def setUp(self) -> None: self.user = User.objects.create_user( email="reorder@example.com", password="testpass123", @@ -44,7 +44,7 @@ def _ordered_names(self, status="in_progress"): .values_list("name", flat=True) ) - def test_reorder_below_visible_anchor_uses_canonical_lower_neighbour(self): + def test_reorder_below_visible_anchor_uses_canonical_lower_neighbour(self) -> None: self._make_job("Bottom") self._make_job("Hidden") anchor = self._make_job("Anchor") @@ -68,7 +68,7 @@ def test_reorder_below_visible_anchor_uses_canonical_lower_neighbour(self): ) self.assertNotIn("800", event.description) - def test_reorder_above_visible_anchor(self): + def test_reorder_above_visible_anchor(self) -> None: anchor = self._make_job("Anchor") mover = self._make_job("Mover") self._make_job("Top") @@ -82,7 +82,7 @@ def test_reorder_above_visible_anchor(self): self.assertEqual(self._ordered_names(), ["Top", "Mover", "Anchor"]) - def test_reorder_without_anchor_places_at_top_of_target_status(self): + def test_reorder_without_anchor_places_at_top_of_target_status(self) -> None: mover = self._make_job("Mover", status="in_progress") KanbanService.reorder_job( @@ -94,7 +94,7 @@ def test_reorder_without_anchor_places_at_top_of_target_status(self): self.assertEqual(self._ordered_names("in_progress"), []) self.assertEqual(self._ordered_names("quoting"), ["Mover"]) - def test_rejects_self_anchor(self): + def test_rejects_self_anchor(self) -> None: mover = self._make_job("Mover") with self.assertRaisesMessage( @@ -107,7 +107,7 @@ def test_rejects_self_anchor(self): staff=self.user, ) - def test_rejects_anchor_in_different_status(self): + def test_rejects_anchor_in_different_status(self) -> None: mover = self._make_job("Mover", status="in_progress") anchor = self._make_job("Anchor", status="quoting") diff --git a/apps/job/tests/test_kanban_search.py b/apps/job/tests/test_kanban_search.py index ca10b5670..610eb5936 100644 --- a/apps/job/tests/test_kanban_search.py +++ b/apps/job/tests/test_kanban_search.py @@ -20,7 +20,7 @@ class KanbanSearchTest(BaseTestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.xero_pay_item = XeroPayItem.get_ordinary_time() self.shop_company = self._make_client("Demo Company Shop") @@ -96,7 +96,9 @@ def _make_quote(self, job: Job, *, number: str) -> Quote: raw_json={}, ) - def test_perform_advanced_search_matches_single_token_job_name_substring(self): + def test_perform_advanced_search_matches_single_token_job_name_substring( + self, + ) -> None: """Catches quick search no longer finding job-name substrings.""" target = self._make_job( name="2 X 1.2MM S/S KICK PLATES 910MM (W) X 300MM (H)", @@ -111,7 +113,9 @@ def test_perform_advanced_search_matches_single_token_job_name_substring(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_serializes_without_lazy_relation_loads(self): + def test_perform_advanced_search_serializes_without_lazy_relation_loads( + self, + ) -> None: """ Catches search results that would lazy-load relations during API serialization (the batched context must cover everything it reads). @@ -157,7 +161,7 @@ def test_search_with_results_does_not_trip_unused_eager_load_guard(self) -> None self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_preloads_quote_for_ranking(self): + def test_perform_advanced_search_preloads_quote_for_ranking(self) -> None: """Catches quote ranking that re-queries quotes per candidate job.""" target = self._make_job( name="Cool Awnings", @@ -183,7 +187,7 @@ def test_perform_advanced_search_preloads_quote_for_ranking(self): ] self.assertEqual(direct_quote_queries, []) - def test_perform_advanced_search_matches_quote_number(self): + def test_perform_advanced_search_matches_quote_number(self) -> None: """Catches quote-number search no longer finding the owning job.""" target = self._make_job( name="Cool Awnings", @@ -202,7 +206,7 @@ def test_perform_advanced_search_matches_quote_number(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_matches_numeric_substring(self): + def test_perform_advanced_search_matches_numeric_substring(self) -> None: """Catches numeric quick search no longer matching job descriptions.""" target = self._make_job( name="2 X 1.2MM S/S KICK PLATES 910MM (W) X 300MM (H)", @@ -217,7 +221,9 @@ def test_perform_advanced_search_matches_numeric_substring(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_numeric_query_prefers_job_number_over_long_description_substring(self): + def test_numeric_query_prefers_job_number_over_long_description_substring( + self, + ) -> None: """Catches job-number matches being buried under description substrings.""" target = self._set_job_number( self._make_job( @@ -244,7 +250,9 @@ def test_numeric_query_prefers_job_number_over_long_description_substring(self): self.assertEqual(jobs[0].id, target.id) self.assertIn(description_match.id, [job.id for job in jobs]) - def test_get_jobs_by_kanban_column_exact_job_number_suppresses_distant_noise(self): + def test_get_jobs_by_kanban_column_exact_job_number_suppresses_distant_noise( + self, + ) -> None: """Catches exact job-number filtering returning nearby numeric noise.""" target = self._set_job_number( self._make_job( @@ -279,7 +287,7 @@ def test_get_jobs_by_kanban_column_exact_job_number_suppresses_distant_noise(sel def test_perform_advanced_search_keeps_plausible_short_job_number_match( self, - ): + ) -> None: """Catches short job-number suffix searches being over-pruned.""" near_match = self._set_job_number( self._make_job( @@ -298,7 +306,9 @@ def test_perform_advanced_search_keeps_plausible_short_job_number_match( self.assertIn(near_match.id, [job.id for job in jobs]) - def test_numeric_query_prefers_job_number_suffix_over_middle_substring(self): + def test_numeric_query_prefers_job_number_suffix_over_middle_substring( + self, + ) -> None: """Catches suffix job-number matches losing to less useful middle matches.""" suffix_match = self._set_job_number( self._make_job( @@ -328,7 +338,7 @@ def test_numeric_query_prefers_job_number_suffix_over_middle_substring(self): ) self.assertLess(middle_score, suffix_score) - def test_perform_advanced_search_keeps_multiple_close_text_matches(self): + def test_perform_advanced_search_keeps_multiple_close_text_matches(self) -> None: """Catches text search collapsing distinct plausible job matches.""" target_one = self._make_job( name="Kick plates", @@ -347,7 +357,7 @@ def test_perform_advanced_search_keeps_multiple_close_text_matches(self): self.assertEqual({job.id for job in jobs}, {target_one.id, target_two.id}) - def test_perform_advanced_search_matches_client_tokens_in_any_order(self): + def test_perform_advanced_search_matches_client_tokens_in_any_order(self) -> None: """Catches company-name token search becoming order-sensitive.""" target = self._make_job( name="Kick plates", @@ -366,7 +376,7 @@ def test_perform_advanced_search_matches_client_tokens_in_any_order(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_matches_person_name_substring(self): + def test_perform_advanced_search_matches_person_name_substring(self) -> None: """Catches contact-name search no longer matching partial names.""" target = self._make_job( name="Kick plates", @@ -383,7 +393,7 @@ def test_perform_advanced_search_matches_person_name_substring(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_get_jobs_by_kanban_column_matches_client_tokens_in_any_order(self): + def test_get_jobs_by_kanban_column_matches_client_tokens_in_any_order(self) -> None: """Catches kanban column search ignoring unordered company-name tokens.""" target = self._make_job( name="Kick plates", @@ -403,7 +413,7 @@ def test_get_jobs_by_kanban_column_matches_client_tokens_in_any_order(self): self.assertTrue(result["success"]) self.assertEqual([job["id"] for job in result["jobs"]], [str(target.id)]) - def test_perform_advanced_search_returns_empty_when_query_not_present(self): + def test_perform_advanced_search_returns_empty_when_query_not_present(self) -> None: """Catches unrelated jobs being returned for absent search terms.""" self._make_job( name="2 X 1.2MM S/S KICK PLATES 910MM (W) X 300MM (H)", @@ -416,7 +426,9 @@ def test_perform_advanced_search_returns_empty_when_query_not_present(self): self.assertEqual(jobs, []) - def test_perform_advanced_search_returns_empty_for_only_weak_trigram_matches(self): + def test_perform_advanced_search_returns_empty_for_only_weak_trigram_matches( + self, + ) -> None: """Catches weak fuzzy matches leaking below the display threshold.""" weak_match = self._make_job( name="5x swaged ends", @@ -435,7 +447,7 @@ def test_perform_advanced_search_returns_empty_for_only_weak_trigram_matches(sel self.assertEqual(ranked_jobs, []) - def test_perform_advanced_search_recovers_typo_tolerance(self): + def test_perform_advanced_search_recovers_typo_tolerance(self) -> None: """Catches typo tolerance no longer recovering misspelled company searches.""" target = self._make_job( name="2 X 1.2MM S/S KICK PLATES 910MM (W) X 300MM (H)", @@ -450,7 +462,7 @@ def test_perform_advanced_search_recovers_typo_tolerance(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_get_jobs_by_kanban_column_recovers_typo_tolerance(self): + def test_get_jobs_by_kanban_column_recovers_typo_tolerance(self) -> None: """Catches kanban column search losing typo tolerance.""" target = self._make_job( name="Kick plates", @@ -465,7 +477,7 @@ def test_get_jobs_by_kanban_column_recovers_typo_tolerance(self): self.assertTrue(result["success"]) self.assertEqual([job["id"] for job in result["jobs"]], [str(target.id)]) - def test_perform_advanced_search_does_not_fuzzy_match_invoice_numbers(self): + def test_perform_advanced_search_does_not_fuzzy_match_invoice_numbers(self) -> None: """Catches invoice searches fuzzily matching the wrong invoice.""" target = self._make_job( name="Kick plates", @@ -484,7 +496,9 @@ def test_perform_advanced_search_does_not_fuzzy_match_invoice_numbers(self): self.assertEqual(jobs, []) - def test_perform_advanced_search_matches_invoice_number_exactly_via_filter(self): + def test_perform_advanced_search_matches_invoice_number_exactly_via_filter( + self, + ) -> None: """Catches the invoice filter failing to match a full invoice number.""" target = self._make_job( name="Kick plates", @@ -503,7 +517,7 @@ def test_perform_advanced_search_matches_invoice_number_exactly_via_filter(self) self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_matches_bare_invoice_number(self): + def test_perform_advanced_search_matches_bare_invoice_number(self) -> None: """Catches the invoice filter failing to match bare invoice digits.""" target = self._make_job( name="Cool Awnings", @@ -522,7 +536,7 @@ def test_perform_advanced_search_matches_bare_invoice_number(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_unrecognised_invoice_returns_empty(self): + def test_perform_advanced_search_unrecognised_invoice_returns_empty(self) -> None: """Catches invalid invoice filters returning unrelated jobs.""" target = self._make_job( name="Kick plates", @@ -536,7 +550,7 @@ def test_perform_advanced_search_unrecognised_invoice_returns_empty(self): self.assertEqual(jobs, []) - def test_perform_advanced_search_quick_search_matches_order_number(self): + def test_perform_advanced_search_quick_search_matches_order_number(self) -> None: """Catches universal search no longer matching order numbers.""" target = self._make_job( name="Cool Awnings", @@ -553,7 +567,7 @@ def test_perform_advanced_search_quick_search_matches_order_number(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_order_number_filter(self): + def test_perform_advanced_search_order_number_filter(self) -> None: """Catches the explicit order-number filter returning the wrong job.""" target = self._make_job( name="Cool Awnings", @@ -570,7 +584,7 @@ def test_perform_advanced_search_order_number_filter(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_quick_search_matches_invoice_number(self): + def test_perform_advanced_search_quick_search_matches_invoice_number(self) -> None: """Catches universal search no longer matching full invoice numbers.""" target = self._make_job( name="Cool Awnings", @@ -589,7 +603,9 @@ def test_perform_advanced_search_quick_search_matches_invoice_number(self): self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_quick_search_matches_bare_invoice_number(self): + def test_perform_advanced_search_quick_search_matches_bare_invoice_number( + self, + ) -> None: """Catches universal search no longer matching bare invoice digits.""" target = self._make_job( name="Cool Awnings", @@ -610,7 +626,7 @@ def test_perform_advanced_search_quick_search_matches_bare_invoice_number(self): def test_perform_advanced_search_invoice_match_returns_job_once_with_multiple_invoices( self, - ): + ) -> None: """Catches invoice joins duplicating jobs with multiple matching invoices.""" target = self._make_job( name="Cool Awnings", @@ -627,7 +643,7 @@ def test_perform_advanced_search_invoice_match_returns_job_once_with_multiple_in def test_perform_advanced_search_text_match_returns_job_once_with_multiple_invoices( self, - ): + ) -> None: """Catches text search duplicating jobs that have multiple invoices.""" target = self._make_job( name="Cool Awnings", @@ -640,7 +656,7 @@ def test_perform_advanced_search_text_match_returns_job_once_with_multiple_invoi self.assertEqual([job.id for job in jobs], [target.id]) - def test_perform_advanced_search_invoice_reason_present(self): + def test_perform_advanced_search_invoice_reason_present(self) -> None: """Catches invoice matches losing their explainable search reason.""" target = self._make_job( name="Cool Awnings", @@ -657,7 +673,7 @@ def test_perform_advanced_search_invoice_reason_present(self): reason_names = [t.get("reason") for t in token_reasons] self.assertIn("invoice_contains", reason_names) - def test_kanban_search_logging_records_ranked_results_and_reasons(self): + def test_kanban_search_logging_records_ranked_results_and_reasons(self) -> None: """Catches search logs losing ranked result and scoring diagnostics.""" target = self._set_job_number( self._make_job( diff --git a/apps/job/tests/test_kanban_service.py b/apps/job/tests/test_kanban_service.py index e91b78b6f..273cd744e 100644 --- a/apps/job/tests/test_kanban_service.py +++ b/apps/job/tests/test_kanban_service.py @@ -18,7 +18,7 @@ class TestSerializeJobForApi(BaseTestCase): """Tests for KanbanService kanban job serialization.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Test Company", xero_last_modified=timezone.now(), @@ -50,7 +50,7 @@ def _link(self, name: str) -> CompanyPersonLink: person=person, ) - def test_over_budget_when_tm_actual_exceeds_price_cap(self): + def test_over_budget_when_tm_actual_exceeds_price_cap(self) -> None: """T&M jobs show over-budget when actual revenue exceeds the price cap.""" job = self._create_job("time_materials") job.price_cap = Decimal("1000.00") @@ -60,7 +60,7 @@ def test_over_budget_when_tm_actual_exceeds_price_cap(self): self.assertTrue(self._serialize_one(job)["over_budget"]) - def test_not_over_budget_when_tm_actual_within_price_cap(self): + def test_not_over_budget_when_tm_actual_within_price_cap(self) -> None: """T&M jobs do not show over-budget when actual revenue stays within the cap.""" job = self._create_job("time_materials") job.price_cap = Decimal("1000.00") @@ -70,7 +70,7 @@ def test_not_over_budget_when_tm_actual_within_price_cap(self): self.assertFalse(self._serialize_one(job)["over_budget"]) - def test_fixed_price_uses_quote_revenue_threshold(self): + def test_fixed_price_uses_quote_revenue_threshold(self) -> None: """Fixed-price jobs compare actual revenue against quote revenue, not price cap.""" job = self._create_job("fixed_price") job.price_cap = Decimal("1000.00") @@ -80,7 +80,7 @@ def test_fixed_price_uses_quote_revenue_threshold(self): self.assertFalse(self._serialize_one(job)["over_budget"]) - def test_serialize_jobs_for_api_query_count_is_constant(self): + def test_serialize_jobs_for_api_query_count_is_constant(self) -> None: """Serialization batches related data: O(1) queries regardless of job count, and no per-job relation lazy loads (each one stalls the dev/E2E n+1 guard with a ~20ms stack inspection).""" @@ -109,7 +109,7 @@ def test_serialize_jobs_for_api_query_count_is_constant(self): ) self.assertLessEqual(len(captured_all.captured_queries), 6) - def test_serialized_shape_for_fully_populated_job(self): + def test_serialized_shape_for_fully_populated_job(self) -> None: """The rewritten serializer must keep the exact response contract the frontend Zod schema requires.""" job = self._create_job(name="Shape Job") @@ -182,7 +182,7 @@ def test_serialized_shape_for_fully_populated_job(self): ) self.assertIsNone(serialized["people"][0]["icon_url"]) - def test_serialize_jobs_for_api_resolves_shop_client_once_for_batch(self): + def test_serialize_jobs_for_api_resolves_shop_client_once_for_batch(self) -> None: shop_job = Job( company=self.shop_company, name="Shop Job", @@ -216,7 +216,7 @@ def test_serialize_jobs_for_api_resolves_shop_client_once_for_batch(self): def test_non_shop_job_serializes_false_when_client_differs_from_configured_shop( self, - ): + ) -> None: job = self._create_job() self._set_summary_revenue(job.latest_actual, Decimal("900.00")) self._set_summary_revenue(job.latest_quote, Decimal("500.00")) diff --git a/apps/job/tests/test_mcp_tool_integration.py b/apps/job/tests/test_mcp_tool_integration.py index a6b1109e8..7f5b61845 100644 --- a/apps/job/tests/test_mcp_tool_integration.py +++ b/apps/job/tests/test_mcp_tool_integration.py @@ -18,7 +18,7 @@ class QuotingToolTests(BaseTestCase): """Test QuotingTool functionality""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" # Create a supplier self.supplier = Company.objects.create( @@ -114,11 +114,11 @@ def setUp(self): self.tool = QuotingTool() - def test_tool_initialization(self): + def test_tool_initialization(self) -> None: """Test tool initializes correctly""" self.assertIsInstance(self.tool, QuotingTool) - def test_search_products_basic(self): + def test_search_products_basic(self) -> None: """Test basic product search functionality""" result = self.tool.search_products(query="steel") @@ -126,33 +126,33 @@ def test_search_products_basic(self): self.assertIn("Steel Plate", result) self.assertIn("ABC Steel", result) - def test_search_products_with_supplier(self): + def test_search_products_with_supplier(self) -> None: """Test product search with supplier filter""" result = self.tool.search_products(query="steel", supplier_name="ABC Steel") self.assertIn("ABC Steel", result) self.assertNotIn("XYZ Metals", result) - def test_search_products_no_results(self): + def test_search_products_no_results(self) -> None: """Test product search with no results""" result = self.tool.search_products(query="nonexistent_material_xyz") self.assertIn("No products found", result) - def test_search_products_case_insensitive(self): + def test_search_products_case_insensitive(self) -> None: """Test that product search is case insensitive""" result = self.tool.search_products(query="STEEL ANGLE") self.assertIn("Steel Angle", result) - def test_get_pricing_for_material(self): + def test_get_pricing_for_material(self) -> None: """Test getting pricing for specific material""" result = self.tool.get_pricing_for_material(material_type="steel") self.assertIn("steel", result.lower()) self.assertIn("ABC Steel", result) - def test_get_pricing_with_dimensions(self): + def test_get_pricing_with_dimensions(self) -> None: """Test getting pricing with dimensions filter""" result = self.tool.get_pricing_for_material( material_type="steel", dimensions="1200x2400" @@ -160,13 +160,13 @@ def test_get_pricing_with_dimensions(self): self.assertIn("1200x2400", result) - def test_get_pricing_no_results(self): + def test_get_pricing_no_results(self) -> None: """Test getting pricing with no matching materials""" result = self.tool.get_pricing_for_material(material_type="titanium") self.assertIn("No pricing found", result) - def test_create_quote_estimate(self): + def test_create_quote_estimate(self) -> None: """Test creating a quote estimate""" result = self.tool.create_quote_estimate( job_id=str(self.job.id), @@ -179,7 +179,7 @@ def test_create_quote_estimate(self): self.assertIn("Labor estimate", result) self.assertIn("15", result) - def test_create_quote_estimate_invalid_job(self): + def test_create_quote_estimate_invalid_job(self) -> None: """Test creating quote for non-existent job""" result = self.tool.create_quote_estimate( job_id="00000000-0000-0000-0000-000000000000", @@ -188,7 +188,7 @@ def test_create_quote_estimate_invalid_job(self): self.assertIn("not found", result) - def test_get_supplier_status(self): + def test_get_supplier_status(self) -> None: """Test getting supplier status""" result = self.tool.get_supplier_status() @@ -196,13 +196,13 @@ def test_get_supplier_status(self): self.assertIn("XYZ Metals", result) self.assertIn("Products:", result) - def test_get_supplier_status_filtered(self): + def test_get_supplier_status_filtered(self) -> None: """Test getting supplier status with filter""" result = self.tool.get_supplier_status(supplier_name="ABC") self.assertIn("ABC Steel", result) - def test_compare_suppliers(self): + def test_compare_suppliers(self) -> None: """Test comparing suppliers for same material""" result = self.tool.compare_suppliers(material_query="steel angle") @@ -210,13 +210,13 @@ def test_compare_suppliers(self): self.assertIn("XYZ Metals", result) self.assertIn("Comparison", result) - def test_compare_suppliers_no_results(self): + def test_compare_suppliers_no_results(self) -> None: """Test comparing suppliers with no matching products""" result = self.tool.compare_suppliers(material_query="nonexistent_xyz") self.assertIn("No products found", result) - def test_calc_sheet_tenths_basic(self): + def test_calc_sheet_tenths_basic(self) -> None: """Test basic sheet tenths calculation""" result = self.tool.calc_sheet_tenths( part_width_mm=600, @@ -227,7 +227,7 @@ def test_calc_sheet_tenths_basic(self): self.assertIn("600", result) self.assertIn("480", result) - def test_calc_sheet_tenths_larger_part(self): + def test_calc_sheet_tenths_larger_part(self) -> None: """Test sheet tenths for larger part spanning multiple sections""" result = self.tool.calc_sheet_tenths( part_width_mm=700, @@ -236,7 +236,7 @@ def test_calc_sheet_tenths_larger_part(self): self.assertIn("4 tenth", result.lower()) - def test_calc_sheet_tenths_custom_sheet_size(self): + def test_calc_sheet_tenths_custom_sheet_size(self) -> None: """Test sheet tenths with custom sheet dimensions""" result = self.tool.calc_sheet_tenths( part_width_mm=500, @@ -252,7 +252,7 @@ def test_calc_sheet_tenths_custom_sheet_size(self): class SupplierProductQueryToolTests(BaseTestCase): """Test SupplierProductQueryTool functionality""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.supplier = Company.objects.create( name="Test Supplier", @@ -277,20 +277,20 @@ def setUp(self): self.tool = SupplierProductQueryTool() - def test_tool_initialization(self): + def test_tool_initialization(self) -> None: """Test tool initializes correctly""" self.assertIsInstance(self.tool, SupplierProductQueryTool) - def test_model_attribute(self): + def test_model_attribute(self) -> None: """Test that model is set to SupplierProduct""" self.assertEqual(self.tool.model, SupplierProduct) - def test_exclude_fields(self): + def test_exclude_fields(self) -> None: """Test that supplier and price_list are excluded""" self.assertIn("supplier", self.tool.exclude_fields) self.assertIn("price_list", self.tool.exclude_fields) - def test_get_queryset(self): + def test_get_queryset(self) -> None: """Test that get_queryset returns products with related data""" queryset = self.tool.get_queryset() product = queryset.first() @@ -302,7 +302,7 @@ def test_get_queryset(self): class MCPToolIntegrationTests(BaseTestCase): """Test MCP tool integration behavior""" - def setUp(self): + def setUp(self) -> None: """Set up test data""" self.supplier = Company.objects.create( name="Integration Test Supplier", @@ -324,7 +324,7 @@ def setUp(self): staff=self.test_staff, ) - def test_tool_parameter_validation(self): + def test_tool_parameter_validation(self) -> None: """Test tool parameter validation""" tool = QuotingTool() @@ -332,7 +332,7 @@ def test_tool_parameter_validation(self): with self.assertRaises(TypeError): tool.search_products() # Missing query parameter - def test_tool_response_is_string(self): + def test_tool_response_is_string(self) -> None: """Test that tools return string responses""" tool = QuotingTool() @@ -342,7 +342,7 @@ def test_tool_response_is_string(self): self.assertIsInstance(result, str) self.assertGreater(len(result), 0) - def test_tool_handles_special_characters(self): + def test_tool_handles_special_characters(self) -> None: """Test that tools handle special characters in queries""" tool = QuotingTool() @@ -350,7 +350,7 @@ def test_tool_handles_special_characters(self): result = tool.search_products(query="steel & aluminium 50%") self.assertIsInstance(result, str) - def test_tool_handles_empty_query(self): + def test_tool_handles_empty_query(self) -> None: """Test that tools handle empty queries gracefully""" tool = QuotingTool() @@ -361,11 +361,11 @@ def test_tool_handles_empty_query(self): class CalcSheetTenthsTests(BaseTestCase): """Dedicated tests for calc_sheet_tenths functionality""" - def setUp(self): + def setUp(self) -> None: """Set up test tool""" self.tool = QuotingTool() - def test_single_section(self): + def test_single_section(self) -> None: """Test part that fits in one section""" result = self.tool.calc_sheet_tenths( part_width_mm=500, @@ -373,7 +373,7 @@ def test_single_section(self): ) self.assertIn("1 tenth", result.lower()) - def test_two_sections_horizontal(self): + def test_two_sections_horizontal(self) -> None: """Test part spanning two sections horizontally""" result = self.tool.calc_sheet_tenths( part_width_mm=700, # > 600, spans 2 columns @@ -381,7 +381,7 @@ def test_two_sections_horizontal(self): ) self.assertIn("2 tenth", result.lower()) - def test_two_sections_vertical(self): + def test_two_sections_vertical(self) -> None: """Test part spanning two sections vertically""" result = self.tool.calc_sheet_tenths( part_width_mm=500, # fits in 1 column @@ -389,7 +389,7 @@ def test_two_sections_vertical(self): ) self.assertIn("2 tenth", result.lower()) - def test_four_sections(self): + def test_four_sections(self) -> None: """Test part spanning 2x2 sections""" result = self.tool.calc_sheet_tenths( part_width_mm=700, @@ -397,7 +397,7 @@ def test_four_sections(self): ) self.assertIn("4 tenth", result.lower()) - def test_full_sheet(self): + def test_full_sheet(self) -> None: """Test part using entire sheet""" result = self.tool.calc_sheet_tenths( part_width_mm=1200, @@ -405,7 +405,7 @@ def test_full_sheet(self): ) self.assertIn("10 tenth", result.lower()) - def test_oversized_part(self): + def test_oversized_part(self) -> None: """Test part larger than sheet""" result = self.tool.calc_sheet_tenths( part_width_mm=1500, diff --git a/apps/job/tests/test_modern_timesheet_views.py b/apps/job/tests/test_modern_timesheet_views.py index 2dcf31633..fc8bb72a1 100644 --- a/apps/job/tests/test_modern_timesheet_views.py +++ b/apps/job/tests/test_modern_timesheet_views.py @@ -14,7 +14,7 @@ class ModernTimesheetEntryQueryTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.target_date = date(2026, 5, 22) self.company = Company.objects.create( @@ -53,7 +53,7 @@ def setUp(self): entry_seq=1, ) - def test_timesheet_cost_line_serializer_uses_preloaded_relations(self): + def test_timesheet_cost_line_serializer_uses_preloaded_relations(self) -> None: cost_lines = ( CostLine.objects.filter(pk=self.cost_line.pk) .select_related( diff --git a/apps/job/tests/test_pdf_goldens.py b/apps/job/tests/test_pdf_goldens.py index 44541926c..787ec03b5 100644 --- a/apps/job/tests/test_pdf_goldens.py +++ b/apps/job/tests/test_pdf_goldens.py @@ -65,7 +65,7 @@ def setUp(self): self.job = build_golden_job(self.test_staff) - def test_delivery_docket_matches_golden(self): + def test_delivery_docket_matches_golden(self) -> None: pdf_buffer, _job_file = generate_delivery_docket( self.job, staff=self.test_staff ) @@ -73,7 +73,7 @@ def test_delivery_docket_matches_golden(self): expected = EXPECTED_DELIVERY_DOCKET.read_bytes() self.assertEqual(actual, expected, msg=REGEN_HINT) - def test_workshop_pdf_matches_golden(self): + def test_workshop_pdf_matches_golden(self) -> None: pdf_buffer = create_workshop_pdf(self.job) actual = pdf_buffer.getvalue() expected = EXPECTED_WORKSHOP.read_bytes() diff --git a/apps/job/tests/test_quote_modes.py b/apps/job/tests/test_quote_modes.py index 58161daab..8350e74a2 100644 --- a/apps/job/tests/test_quote_modes.py +++ b/apps/job/tests/test_quote_modes.py @@ -21,7 +21,7 @@ class TestQuoteModeSchemas(TestCase): """Test the JSON schemas for each mode.""" - def test_calc_schema_valid(self): + def test_calc_schema_valid(self) -> None: """Test valid CALC schema data.""" valid_data = { "inputs": { @@ -48,7 +48,7 @@ def test_calc_schema_valid(self): validate(instance=valid_data, schema=schema) - def test_calc_schema_invalid_missing_required(self): + def test_calc_schema_invalid_missing_required(self) -> None: """Test CALC schema validation with missing required fields.""" invalid_data = { "inputs": {"units": "mm"}, @@ -61,7 +61,7 @@ def test_calc_schema_invalid_missing_required(self): with self.assertRaises(ValidationError): validate(instance=invalid_data, schema=schema) - def test_price_schema_valid(self): + def test_price_schema_valid(self) -> None: """Test valid PRICE schema data.""" valid_data = { "normalized": { @@ -92,7 +92,7 @@ def test_price_schema_valid(self): validate(instance=valid_data, schema=schema) - def test_table_schema_valid(self): + def test_table_schema_valid(self) -> None: """Test valid TABLE schema data.""" valid_data = { "rows": [ @@ -121,7 +121,7 @@ def test_table_schema_valid(self): validate(instance=valid_data, schema=schema) - def test_get_allowed_tools(self): + def test_get_allowed_tools(self) -> None: """Test tool gating for each mode.""" # CALC mode should have sheet tenths tool and emit tool calc_tools = quote_mode_schemas.get_allowed_tools("CALC") @@ -142,7 +142,7 @@ def test_get_allowed_tools(self): class TestQuoteModeController(BaseTestCase): """Test the QuoteModeController functionality.""" - def setUp(self): + def setUp(self) -> None: """Set up test fixtures.""" self.controller = QuoteModeController() @@ -221,7 +221,7 @@ def test_mode_inference_table(self, mock_llm_class): mode = self.controller.infer_mode(input_text) self.assertEqual(mode, "TABLE", f"Failed to infer TABLE for: {input_text}") - def test_system_prompt(self): + def test_system_prompt(self) -> None: """Test that system prompt is appropriate for mode-based operation.""" prompt = self.controller.get_system_prompt() @@ -234,7 +234,7 @@ def test_system_prompt(self): self.assertIn("emit_table_result", prompt) self.assertIn("MUST call", prompt) - def test_render_prompt(self): + def test_render_prompt(self) -> None: """Test prompt rendering for each mode.""" # Test CALC prompt calc_prompt = self.controller.render_prompt( @@ -260,7 +260,7 @@ def test_render_prompt(self): self.assertIn("MODE=TABLE", table_prompt) self.assertIn("emit_table_result", table_prompt) - def test_validate_json(self): + def test_validate_json(self) -> None: """Test JSON validation against schemas.""" # Valid data should pass valid_calc_data = { @@ -281,7 +281,7 @@ def test_validate_json(self): with self.assertRaises(ValidationError): self.controller.validate_json(invalid_data, self.controller.schemas["CALC"]) - def test_get_mcp_tools_for_mode(self): + def test_get_mcp_tools_for_mode(self) -> None: """Test that correct tools are returned for each mode.""" # CALC mode - calc_sheet_tenths and emit tool calc_tools = self.controller.get_mcp_tools_for_mode("CALC") @@ -304,7 +304,7 @@ def test_get_mcp_tools_for_mode(self): self.assertEqual(len(table_tools), 1) self.assertEqual(table_tools[0]["function"]["name"], "emit_table_result") - def test_invalid_mode(self): + def test_invalid_mode(self) -> None: """Test that invalid mode raises ValueError.""" with self.assertRaises(ValueError) as context: self.controller.run(mode="INVALID", user_input="Test", job=None) @@ -314,7 +314,7 @@ def test_invalid_mode(self): class TestSheetTenthsIntegration(BaseTestCase): """Integration tests for sheet tenths calculation in CALC mode.""" - def setUp(self): + def setUp(self) -> None: """Set up test fixtures.""" # Create test job self.client_obj = Company.objects.create( diff --git a/apps/job/tests/test_workshop_pdf_service.py b/apps/job/tests/test_workshop_pdf_service.py index 781bd7ed2..d1907a67b 100644 --- a/apps/job/tests/test_workshop_pdf_service.py +++ b/apps/job/tests/test_workshop_pdf_service.py @@ -101,29 +101,29 @@ def test_annotated_job_falls_back_to_client_phone(self) -> None: class FormatHoursDisplayTests(SimpleTestCase): """Tests for the format_hours_display function.""" - def test_whole_hours(self): + def test_whole_hours(self) -> None: self.assertEqual(format_hours_display(2.0), "2h") - def test_hours_and_minutes(self): + def test_hours_and_minutes(self) -> None: self.assertEqual(format_hours_display(2.5), "2h 30m") - def test_minutes_only(self): + def test_minutes_only(self) -> None: self.assertEqual(format_hours_display(0.25), "15m") - def test_zero(self): + def test_zero(self) -> None: self.assertEqual(format_hours_display(0.0), "0h") - def test_none(self): + def test_none(self) -> None: self.assertEqual(format_hours_display(None), "0h") - def test_large_value(self): + def test_large_value(self) -> None: self.assertEqual(format_hours_display(10.75), "10h 45m") - def test_rounding(self): + def test_rounding(self) -> None: # 1.33 hours = 79.8 minutes, rounds to 80 = 1h 20m self.assertEqual(format_hours_display(1.33), "1h 20m") - def test_integer_input(self): + def test_integer_input(self) -> None: self.assertEqual(format_hours_display(3), "3h") @@ -134,25 +134,25 @@ class ConvertHtmlToReportlabTests(SimpleTestCase): # Basic paragraph handling - the core fix for preserving newlines # ------------------------------------------------------------------------- - def test_simple_paragraphs_preserve_line_breaks(self): + def test_simple_paragraphs_preserve_line_breaks(self) -> None: """Each

tag should create a line break in the output.""" html = "

Line 1

Line 2

Line 3

" result = convert_html_to_reportlab(html) self.assertEqual(result, "Line 1
Line 2
Line 3") - def test_blank_line_creates_paragraph_spacing(self): + def test_blank_line_creates_paragraph_spacing(self) -> None: """Quill's blank line (


) should create double line break.""" html = "

Section 1


Section 2

" result = convert_html_to_reportlab(html) self.assertEqual(result, "Section 1

Section 2") - def test_multiple_blank_lines_collapse_to_two(self): + def test_multiple_blank_lines_collapse_to_two(self) -> None: """Multiple consecutive blank lines should collapse to max 2 breaks.""" html = "

Section 1




Section 2

" result = convert_html_to_reportlab(html) self.assertEqual(result, "Section 1

Section 2") - def test_trailing_blank_lines_stripped(self): + def test_trailing_blank_lines_stripped(self) -> None: """Trailing blank lines should be removed.""" html = "

Content



" result = convert_html_to_reportlab(html) @@ -162,7 +162,7 @@ def test_trailing_blank_lines_stripped(self): # Real job notes from database - Job 96577 (RACK AND TABLE) # ------------------------------------------------------------------------- - def test_real_job_96577_rack_and_table(self): + def test_real_job_96577_rack_and_table(self) -> None: """ Real job notes with bold headers and blank line section separator. Should preserve structure with line breaks between items. @@ -196,7 +196,7 @@ def test_real_job_96577_rack_and_table(self): # Real job notes - Job 96573 (Kitchen wall structural) # ------------------------------------------------------------------------- - def test_real_job_96573_structural_with_inline_bold(self): + def test_real_job_96573_structural_with_inline_bold(self) -> None: """ Real job with inline bold text within a paragraph. Tests that partial bold formatting is preserved correctly. @@ -215,7 +215,7 @@ def test_real_job_96573_structural_with_inline_bold(self): # Real job notes - Job 96567 (with underline) # ------------------------------------------------------------------------- - def test_real_job_96567_with_underline(self): + def test_real_job_96567_with_underline(self) -> None: """ Real job with underlined section headers. Tests that tags are preserved. @@ -244,7 +244,7 @@ def test_real_job_96567_with_underline(self): # Real job notes - Job 96576 (with styled spans) # ------------------------------------------------------------------------- - def test_real_job_96576_strips_style_attributes(self): + def test_real_job_96576_strips_style_attributes(self) -> None: """ Real job with Quill's inline style spans. Style attributes should be stripped, content preserved. @@ -269,21 +269,21 @@ def test_real_job_96576_strips_style_attributes(self): # Edge cases # ------------------------------------------------------------------------- - def test_empty_string_returns_na(self): + def test_empty_string_returns_na(self) -> None: """Empty string should return N/A.""" self.assertEqual(convert_html_to_reportlab(""), "N/A") - def test_none_returns_na(self): + def test_none_returns_na(self) -> None: """None should return N/A.""" self.assertEqual(convert_html_to_reportlab(None), "N/A") - def test_plain_text_without_tags(self): + def test_plain_text_without_tags(self) -> None: """Plain text without HTML tags should pass through unchanged.""" text = "Plain text without any HTML" result = convert_html_to_reportlab(text) self.assertEqual(result, text) - def test_whitespace_only_returns_na(self): + def test_whitespace_only_returns_na(self) -> None: """Whitespace-only content should return N/A.""" self.assertEqual(convert_html_to_reportlab(" \n\t "), "N/A") @@ -291,28 +291,28 @@ def test_whitespace_only_returns_na(self): # Formatting tag conversions # ------------------------------------------------------------------------- - def test_strong_converts_to_b(self): + def test_strong_converts_to_b(self) -> None: """ should convert to .""" html = "

Bold text

" result = convert_html_to_reportlab(html) self.assertIn("Bold text", result) self.assertNotIn("", result) - def test_em_converts_to_i(self): + def test_em_converts_to_i(self) -> None: """ should convert to .""" html = "

Italic text

" result = convert_html_to_reportlab(html) self.assertIn("Italic text", result) self.assertNotIn("", result) - def test_s_converts_to_strike(self): + def test_s_converts_to_strike(self) -> None: """ (strikethrough) should convert to .""" html = "

Struck text

" result = convert_html_to_reportlab(html) self.assertIn("Struck text", result) self.assertNotIn("", result) - def test_anchor_converts_to_link(self): + def test_anchor_converts_to_link(self) -> None: """ should convert to .""" html = '

Click here

' result = convert_html_to_reportlab(html) @@ -323,7 +323,7 @@ def test_anchor_converts_to_link(self): # List handling # ------------------------------------------------------------------------- - def test_ordered_list_converts_to_numbered(self): + def test_ordered_list_converts_to_numbered(self) -> None: """
    should convert to numbered list with line breaks.""" html = "
    1. First
    2. Second
    3. Third
    " result = convert_html_to_reportlab(html) @@ -331,7 +331,7 @@ def test_ordered_list_converts_to_numbered(self): self.assertIn("2. Second", result) self.assertIn("3. Third", result) - def test_unordered_list_converts_to_bullets(self): + def test_unordered_list_converts_to_bullets(self) -> None: """
      should convert to bullet list with line breaks.""" html = "
      • Apple
      • Banana
      " result = convert_html_to_reportlab(html) @@ -342,13 +342,13 @@ def test_unordered_list_converts_to_bullets(self): # Heading handling # ------------------------------------------------------------------------- - def test_h1_converts_to_font_size_bold(self): + def test_h1_converts_to_font_size_bold(self) -> None: """

      should convert to large bold text.""" html = "

      Main Heading

      " result = convert_html_to_reportlab(html) self.assertIn('Main Heading', result) - def test_h2_converts_to_font_size_bold(self): + def test_h2_converts_to_font_size_bold(self) -> None: """

      should convert to bold text with appropriate size.""" html = "

      Sub Heading

      " result = convert_html_to_reportlab(html) @@ -358,19 +358,19 @@ def test_h2_converts_to_font_size_bold(self): # Special elements # ------------------------------------------------------------------------- - def test_blockquote_converts_to_italic(self): + def test_blockquote_converts_to_italic(self) -> None: """
      should convert to italic.""" html = "
      Quoted text
      " result = convert_html_to_reportlab(html) self.assertIn("Quoted text", result) - def test_pre_converts_to_courier_font(self): + def test_pre_converts_to_courier_font(self) -> None: """
       should convert to Courier font."""
               html = "
      Code block
      " result = convert_html_to_reportlab(html) self.assertIn('Code block', result) - def test_br_tags_preserved(self): + def test_br_tags_preserved(self) -> None: """
      tags should be preserved as
      .""" html = "

      Line one
      Line two

      " result = convert_html_to_reportlab(html) @@ -380,7 +380,7 @@ def test_br_tags_preserved(self): # Quill UI element removal # ------------------------------------------------------------------------- - def test_quill_ui_spans_removed(self): + def test_quill_ui_spans_removed(self) -> None: """Quill UI elements (class='ql-ui') should be completely removed.""" html = '

      TextUI elementMore text

      ' result = convert_html_to_reportlab(html) diff --git a/apps/operations/tests/test_scheduler_persistence.py b/apps/operations/tests/test_scheduler_persistence.py index 2626ac90e..3a9230a4c 100644 --- a/apps/operations/tests/test_scheduler_persistence.py +++ b/apps/operations/tests/test_scheduler_persistence.py @@ -73,7 +73,7 @@ def _make_job(company: Company, staff: Staff, name: str = "Persist Test Job") -> class TestSchedulerRunRecord(BaseTestCase): """Verify SchedulerRun records are created correctly.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Persist Company", xero_last_modified=timezone.now(), @@ -81,17 +81,17 @@ def setUp(self): _make_staff("p1") _make_job(self.client_obj, self.test_staff) - def test_successful_run_creates_scheduler_run_record(self): + def test_successful_run_creates_scheduler_run_record(self) -> None: """A successful run creates exactly one SchedulerRun record.""" run_workshop_schedule() self.assertEqual(SchedulerRun.objects.count(), 1) - def test_successful_run_creates_job_projections(self): + def test_successful_run_creates_job_projections(self) -> None: """A successful run creates JobProjection records.""" run = run_workshop_schedule() self.assertTrue(JobProjection.objects.filter(scheduler_run=run).exists()) - def test_successful_run_creates_allocation_blocks(self): + def test_successful_run_creates_allocation_blocks(self) -> None: """A successful run creates AllocationBlock records.""" run = run_workshop_schedule() self.assertTrue(AllocationBlock.objects.filter(scheduler_run=run).exists()) @@ -100,7 +100,7 @@ def test_successful_run_creates_allocation_blocks(self): class TestFailedRunPreservesData(BaseTestCase): """Verify a failed run does not overwrite good data from a previous run.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Persist Company", xero_last_modified=timezone.now(), @@ -108,7 +108,7 @@ def setUp(self): _make_staff("p2") _make_job(self.client_obj, self.test_staff) - def test_failed_run_preserves_last_successful(self): + def test_failed_run_preserves_last_successful(self) -> None: """After a failed run, the previously successful SchedulerRun still exists.""" # First successful run first_run = run_workshop_schedule() @@ -127,7 +127,7 @@ def test_failed_run_preserves_last_successful(self): # Original successful run still present self.assertTrue(SchedulerRun.objects.filter(id=first_run.id).exists()) - def test_failed_run_does_not_overwrite_good_data(self): + def test_failed_run_does_not_overwrite_good_data(self) -> None: """Old projections still exist after a failed run attempt.""" first_run = run_workshop_schedule() original_projection_count = JobProjection.objects.filter( @@ -154,14 +154,14 @@ def test_failed_run_does_not_overwrite_good_data(self): class TestLatestForecastReadsNewestRun(BaseTestCase): """Verify the API reads from the most recent successful SchedulerRun.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Persist Company", xero_last_modified=timezone.now(), ) _make_staff("p3") - def test_latest_forecast_from_latest_successful_run(self): + def test_latest_forecast_from_latest_successful_run(self) -> None: """Two successful runs exist; the API reads data from the newer run.""" job1 = _make_job(self.client_obj, self.test_staff, name="Job One") run_workshop_schedule() diff --git a/apps/operations/tests/test_scheduler_service.py b/apps/operations/tests/test_scheduler_service.py index b55ed8ba3..7d4e6863e 100644 --- a/apps/operations/tests/test_scheduler_service.py +++ b/apps/operations/tests/test_scheduler_service.py @@ -87,11 +87,11 @@ def _set_summary_hours(cost_set: CostSet, hours: float) -> None: class TestHoursComputation(BaseTestCase): """Tests for how remaining hours are computed from estimate/quote/actual.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = _make_client() _make_staff("worker1") - def test_estimate_hours_used_when_present(self): + def test_estimate_hours_used_when_present(self) -> None: """Job with estimate hours schedules; remaining = estimate - actual at run time.""" job = _make_job(self.client_obj, self.test_staff) _set_summary_hours(job.latest_estimate, 10.0) @@ -104,7 +104,7 @@ def test_estimate_hours_used_when_present(self): # not the post-simulation residual. self.assertAlmostEqual(proj.remaining_hours, 10.0, delta=0.1) - def test_quote_fallback_when_estimate_zero(self): + def test_quote_fallback_when_estimate_zero(self) -> None: """Job with zero estimate but valid quote schedules using quote hours.""" job = _make_job(self.client_obj, self.test_staff) _set_summary_hours(job.latest_estimate, 0.0) @@ -116,7 +116,7 @@ def test_quote_fallback_when_estimate_zero(self): self.assertFalse(proj.is_unscheduled) self.assertAlmostEqual(proj.remaining_hours, 8.0, delta=0.1) - def test_non_workshop_estimate_hours_are_ignored(self): + def test_non_workshop_estimate_hours_are_ignored(self) -> None: """Office-like estimate lines do not create schedulable work.""" job = _make_job(self.client_obj, self.test_staff) admin = LabourSubtype.objects.get(name="Admin") @@ -140,7 +140,7 @@ def test_non_workshop_estimate_hours_are_ignored(self): UnscheduledReason.MISSING_ESTIMATE_OR_QUOTE_HOURS, ) - def test_onsite_estimate_hours_are_scheduled(self): + def test_onsite_estimate_hours_are_scheduled(self) -> None: """Onsite work consumes the same schedulable staff capacity as workshop work.""" job = _make_job(self.client_obj, self.test_staff) onsite = LabourSubtype.objects.get(name="Onsite") @@ -161,7 +161,7 @@ def test_onsite_estimate_hours_are_scheduled(self): self.assertFalse(proj.is_unscheduled) self.assertAlmostEqual(proj.remaining_hours, 6.0, delta=0.1) - def test_remaining_hours_is_at_run_time_not_post_simulation(self): + def test_remaining_hours_is_at_run_time_not_post_simulation(self) -> None: """Multi-day jobs persist the at-run-time remaining hours, not the post-simulation residual. The frontend needs to display 'X hours of work left' — once the simulation has consumed the work, that value is 0, @@ -176,7 +176,7 @@ def test_remaining_hours_is_at_run_time_not_post_simulation(self): self.assertFalse(proj.is_unscheduled) self.assertAlmostEqual(proj.remaining_hours, 24.0, delta=0.1) - def test_no_hours_unscheduled(self): + def test_no_hours_unscheduled(self) -> None: """Job with no hours in estimate or quote is unscheduled.""" job = _make_job(self.client_obj, self.test_staff) # Both estimate and quote have 0 hours by default @@ -190,7 +190,7 @@ def test_no_hours_unscheduled(self): UnscheduledReason.MISSING_ESTIMATE_OR_QUOTE_HOURS, ) - def test_zero_remaining_hours_excluded(self): + def test_zero_remaining_hours_excluded(self) -> None: """Job where actual >= estimate is unscheduled (not actively allocated).""" from apps.workflow.models import XeroPayItem @@ -226,7 +226,7 @@ def test_zero_remaining_hours_excluded(self): proj = JobProjection.objects.get(scheduler_run=run, job=job) self.assertTrue(proj.is_unscheduled) - def test_non_workshop_actual_time_does_not_reduce_remaining_hours(self): + def test_non_workshop_actual_time_does_not_reduce_remaining_hours(self) -> None: """Admin actual time does not consume workshop scheduled hours.""" from apps.workflow.models import XeroPayItem @@ -266,10 +266,10 @@ def test_non_workshop_actual_time_does_not_reduce_remaining_hours(self): class TestStaffFiltering(BaseTestCase): """Tests for which staff participate in scheduling.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = _make_client() - def test_only_workshop_staff_contribute(self): + def test_only_workshop_staff_contribute(self) -> None: """Non-workshop staff are excluded from allocation.""" office_staff = _make_staff("office", is_workshop=False) workshop_staff = _make_staff("shop") @@ -286,7 +286,7 @@ def test_only_workshop_staff_contribute(self): self.assertNotIn(office_staff.id, staff_ids) self.assertIn(workshop_staff.id, staff_ids) - def test_impossible_staffing_unscheduled(self): + def test_impossible_staffing_unscheduled(self) -> None: """min_people > available staff count causes unscheduled with correct reason.""" _make_staff("solo") # only 1 workshop staff @@ -306,10 +306,10 @@ def test_impossible_staffing_unscheduled(self): class TestPeopleAssignment(BaseTestCase): """Tests for min/max people constraints during allocation.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = _make_client() - def test_one_person_default(self): + def test_one_person_default(self) -> None: """Job with min=1, max=1 gets exactly one worker per day.""" _make_staff("w1") _make_staff("w2") @@ -330,7 +330,7 @@ def test_one_person_default(self): for day in per_day: self.assertEqual(day["count"], 1) - def test_multi_person_job(self): + def test_multi_person_job(self) -> None: """Job with min_people=2 gets at least 2 workers when enough staff available.""" _make_staff("w1") _make_staff("w2") @@ -359,10 +359,10 @@ def test_multi_person_job(self): class TestAssignedStaffPreference(BaseTestCase): """Tests that explicitly-assigned staff are preferred when available.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = _make_client() - def test_assigned_available_staff_chosen_over_others(self): + def test_assigned_available_staff_chosen_over_others(self) -> None: """When a job has assigned staff and they're available, they get the work.""" # Three workers — without assignment, the scheduler picks by capacity # which would tie and fall back to insertion order. @@ -381,7 +381,7 @@ def test_assigned_available_staff_chosen_over_others(self): staff_ids = set(blocks.values_list("staff_id", flat=True)) self.assertEqual(staff_ids, {w1.id}) - def test_assigned_staff_preferred_even_with_lower_capacity(self): + def test_assigned_staff_preferred_even_with_lower_capacity(self) -> None: """Assigned worker is picked over a non-assigned worker with more remaining capacity (capacity sort would otherwise win).""" # Big-capacity worker is unassigned; small-capacity worker is assigned. @@ -400,7 +400,7 @@ def test_assigned_staff_preferred_even_with_lower_capacity(self): self.assertIn(small.id, staff_ids) self.assertNotIn(big.id, staff_ids) - def test_remaining_slots_filled_from_unassigned_pool(self): + def test_remaining_slots_filled_from_unassigned_pool(self) -> None: """If max_people exceeds the number of assigned staff, remaining slots are filled from the unassigned pool.""" w1 = _make_staff("w1") @@ -424,7 +424,7 @@ def test_remaining_slots_filled_from_unassigned_pool(self): # Second slot must be one of the others self.assertTrue({w2.id, w3.id} & first_day_staff) - def test_unavailable_assigned_staff_falls_back_to_others(self): + def test_unavailable_assigned_staff_falls_back_to_others(self) -> None: """If the assigned worker has no capacity today, the scheduler still picks an available worker rather than skipping the job.""" # Assigned worker doesn't work any day (no scheduled hours) @@ -460,7 +460,7 @@ class TestBookedTimeReducesCapacity(BaseTestCase): """Tests that pre-existing time CostLines (worked time, leave) reduce a staff member's available capacity for the day.""" - def setUp(self): + def setUp(self) -> None: from apps.workflow.models.company_defaults import CompanyDefaults self.client_obj = _make_client() @@ -505,7 +505,7 @@ def _book_time(self, staff, on_date, hours, cost_set): }, ) - def test_full_day_leave_blocks_allocation(self): + def test_full_day_leave_blocks_allocation(self) -> None: """A full-day leave entry on day D removes that worker from day D.""" on_leave = _make_staff("on_leave") backup = _make_staff("backup") @@ -532,7 +532,7 @@ def test_full_day_leave_blocks_allocation(self): self.assertNotIn(on_leave.id, staff_ids) self.assertIn(backup.id, staff_ids) - def test_partial_day_booking_reduces_capacity(self): + def test_partial_day_booking_reduces_capacity(self) -> None: """Pre-booking 4h leaves only the remaining 4h available that day.""" worker = _make_staff("part") leave_job = self._make_special_leave_job() @@ -561,7 +561,7 @@ def test_partial_day_booking_reduces_capacity(self): # Capacity reduced from 8h to 4h self.assertAlmostEqual(first_day_total, 4.0, delta=0.01) - def test_estimate_or_quote_costlines_do_not_reduce_capacity(self): + def test_estimate_or_quote_costlines_do_not_reduce_capacity(self) -> None: """CostLines on estimate/quote CostSets are hypothetical and must not reduce real capacity.""" worker = _make_staff("solo") @@ -615,7 +615,7 @@ class TestStartDateOnlyOnRealWork(BaseTestCase): low-priority jobs whose chosen workers had drained capacity got start_date=today + zero AllocationBlocks.""" - def setUp(self): + def setUp(self) -> None: from apps.workflow.models.company_defaults import CompanyDefaults self.client_obj = _make_client() @@ -623,7 +623,7 @@ def setUp(self): cd.workshop_efficiency_factor = Decimal("1.000") cd.save() - def test_low_priority_job_does_not_start_on_capacity_starved_day(self): + def test_low_priority_job_does_not_start_on_capacity_starved_day(self) -> None: """One worker, two jobs needing one person each. High-priority job consumes the day's capacity. Low-priority job must NOT have its start_date set to the same day — it can't have started yet.""" @@ -657,7 +657,7 @@ def test_low_priority_job_does_not_start_on_capacity_starved_day(self): ) self.assertTrue(first_blocks.exists()) - def test_unreachable_job_marked_unscheduled(self): + def test_unreachable_job_marked_unscheduled(self) -> None: """A schedulable job whose simulation never lands any work in the horizon is recorded as unscheduled with NOT_REACHED_IN_HORIZON.""" # One worker, one always-busy high-priority job that never finishes, @@ -693,7 +693,7 @@ class TestEfficiencyFactor(BaseTestCase): """Tests that CompanyDefaults.workshop_efficiency_factor scales daily schedulable capacity.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = _make_client() def _set_efficiency(self, value): @@ -703,7 +703,7 @@ def _set_efficiency(self, value): cd.workshop_efficiency_factor = Decimal(str(value)) cd.save() - def test_factor_scales_daily_allocation(self): + def test_factor_scales_daily_allocation(self) -> None: """At 0.75, an 8h-shift worker delivers 6h on day one of an 8h job.""" worker = _make_staff("w") self._set_efficiency("0.750") @@ -727,7 +727,7 @@ def test_factor_scales_daily_allocation(self): ) self.assertAlmostEqual(first_day_total, 6.0, delta=0.01) - def test_factor_one_means_full_capacity(self): + def test_factor_one_means_full_capacity(self) -> None: """Setting efficiency to 1.0 restores nominal clock-hour capacity.""" worker = _make_staff("w") self._set_efficiency("1.000") @@ -755,11 +755,11 @@ def test_factor_one_means_full_capacity(self): class TestAllocationBlocks(BaseTestCase): """Tests for AllocationBlock creation and content.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = _make_client() _make_staff("worker1") - def test_anticipated_staff_populated(self): + def test_anticipated_staff_populated(self) -> None: """Scheduled job has AllocationBlock records linking staff to the job.""" job = _make_job(self.client_obj, self.test_staff) _set_summary_hours(job.latest_estimate, 8.0) @@ -769,7 +769,7 @@ def test_anticipated_staff_populated(self): blocks = AllocationBlock.objects.filter(scheduler_run=run, job=job) self.assertTrue(blocks.exists()) - def test_allocation_blocks_persisted(self): + def test_allocation_blocks_persisted(self) -> None: """AllocationBlock records exist after a scheduler run.""" job = _make_job(self.client_obj, self.test_staff) _set_summary_hours(job.latest_estimate, 8.0) @@ -782,11 +782,11 @@ def test_allocation_blocks_persisted(self): class TestDateCalculations(BaseTestCase): """Tests for anticipated start/end date assignment.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = _make_client() _make_staff("worker1") - def test_today_uses_local_timezone_not_utc(self): + def test_today_uses_local_timezone_not_utc(self) -> None: """The scheduler must anchor 'today' on the project's local timezone (Pacific/Auckland). Using timezone.now().date() returns the UTC date, so for half the day in NZ the schedule shows yesterday as today.""" @@ -803,7 +803,7 @@ def test_today_uses_local_timezone_not_utc(self): self.assertIsNotNone(earliest_block) self.assertGreaterEqual(earliest_block.allocation_date, timezone.localdate()) - def test_start_date_is_first_allocation_day(self): + def test_start_date_is_first_allocation_day(self) -> None: """anticipated_start_date equals the earliest AllocationBlock date.""" job = _make_job(self.client_obj, self.test_staff) _set_summary_hours(job.latest_estimate, 8.0) @@ -818,7 +818,7 @@ def test_start_date_is_first_allocation_day(self): ) self.assertEqual(proj.anticipated_start_date, earliest_block.allocation_date) - def test_end_date_is_last_allocation_day(self): + def test_end_date_is_last_allocation_day(self) -> None: """anticipated_end_date equals the latest AllocationBlock date.""" job = _make_job(self.client_obj, self.test_staff) _set_summary_hours(job.latest_estimate, 8.0) @@ -833,7 +833,7 @@ def test_end_date_is_last_allocation_day(self): ) self.assertEqual(proj.anticipated_end_date, latest_block.allocation_date) - def test_multi_day_job_carries_over(self): + def test_multi_day_job_carries_over(self) -> None: """Job with more hours than one day spans multiple working days.""" job = _make_job(self.client_obj, self.test_staff) # 1 worker @ 8h/day, 24h of work needs at least 3 days @@ -845,7 +845,7 @@ def test_multi_day_job_carries_over(self): self.assertFalse(proj.is_unscheduled) self.assertGreater(proj.anticipated_end_date, proj.anticipated_start_date) - def test_scheduled_job_has_both_dates(self): + def test_scheduled_job_has_both_dates(self) -> None: """Every scheduled projection has non-null start and end dates.""" job = _make_job(self.client_obj, self.test_staff) _set_summary_hours(job.latest_estimate, 8.0) @@ -862,10 +862,10 @@ def test_scheduled_job_has_both_dates(self): class TestPriorityAndCapacity(BaseTestCase): """Tests for priority ordering and capacity consumption.""" - def setUp(self): + def setUp(self) -> None: self.client_obj = _make_client() - def test_priority_order_affects_scheduling(self): + def test_priority_order_affects_scheduling(self) -> None: """Higher priority job starts no later than lower priority job.""" _make_staff("w1") diff --git a/apps/operations/tests/test_workshop_schedule_api.py b/apps/operations/tests/test_workshop_schedule_api.py index f6c82eb85..5aba59aaf 100644 --- a/apps/operations/tests/test_workshop_schedule_api.py +++ b/apps/operations/tests/test_workshop_schedule_api.py @@ -78,7 +78,7 @@ def _make_job( class WorkshopScheduleGetTests(BaseAPITestCase): """Tests for GET /api/operations/workshop-schedule/""" - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="API Test Company", xero_last_modified=timezone.now(), @@ -88,7 +88,7 @@ def setUp(self): self.api_client.force_authenticate(user=self.staff) self.url = reverse("operations:workshop-schedule") - def test_no_run_returns_empty_response(self): + def test_no_run_returns_empty_response(self) -> None: """GET with no SchedulerRun returns empty lists.""" response = self.api_client.get(self.url) self.assertEqual(response.status_code, 200) @@ -97,7 +97,7 @@ def test_no_run_returns_empty_response(self): self.assertEqual(data["jobs"], []) self.assertEqual(data["unscheduled_jobs"], []) - def test_get_returns_expected_shape(self): + def test_get_returns_expected_shape(self) -> None: """GET returns 200 with days, jobs, and unscheduled_jobs keys.""" _make_job(self.client_obj, self.test_staff) run_workshop_schedule() @@ -109,7 +109,7 @@ def test_get_returns_expected_shape(self): self.assertIn("jobs", data) self.assertIn("unscheduled_jobs", data) - def test_scheduled_job_has_dates(self): + def test_scheduled_job_has_dates(self) -> None: """Scheduled jobs include anticipated_start_date and anticipated_end_date.""" _make_job(self.client_obj, self.test_staff) run_workshop_schedule() @@ -122,7 +122,7 @@ def test_scheduled_job_has_dates(self): self.assertIn("anticipated_start_date", job) self.assertIn("anticipated_end_date", job) - def test_scheduled_job_has_people_fields(self): + def test_scheduled_job_has_people_fields(self) -> None: """Scheduled jobs include min_people, max_people, and assigned_staff.""" _make_job(self.client_obj, self.test_staff) run_workshop_schedule() @@ -135,7 +135,7 @@ def test_scheduled_job_has_people_fields(self): self.assertIn("max_people", job) self.assertIn("assigned_staff", job) - def test_unscheduled_job_has_reason(self): + def test_unscheduled_job_has_reason(self) -> None: """Unscheduled jobs include a machine-readable reason field.""" # Job with no hours → unscheduled Job.objects.create( @@ -156,7 +156,7 @@ def test_unscheduled_job_has_reason(self): self.assertIn("reason", unscheduled) self.assertTrue(len(unscheduled["reason"]) > 0) - def test_invalid_day_horizon_returns_400(self): + def test_invalid_day_horizon_returns_400(self) -> None: """GET with day_horizon=0 returns 400.""" response = self.api_client.get(self.url, {"day_horizon": 0}) self.assertEqual(response.status_code, 400) @@ -165,7 +165,7 @@ def test_invalid_day_horizon_returns_400(self): class WorkshopScheduleRecalculateTests(BaseAPITestCase): """Tests for POST /api/operations/workshop-schedule/recalculate/""" - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Recalc Test Company", xero_last_modified=timezone.now(), @@ -176,7 +176,7 @@ def setUp(self): self.url = reverse("operations:workshop-schedule-recalculate") self.get_url = reverse("operations:workshop-schedule") - def test_post_recalculate_returns_same_shape(self): + def test_post_recalculate_returns_same_shape(self) -> None: """POST to recalculate returns 200 with days, jobs, unscheduled_jobs.""" _make_job(self.client_obj, self.test_staff) @@ -187,7 +187,7 @@ def test_post_recalculate_returns_same_shape(self): self.assertIn("jobs", data) self.assertIn("unscheduled_jobs", data) - def test_post_recalculate_supports_quote_fallback_hours(self): + def test_post_recalculate_supports_quote_fallback_hours(self) -> None: """Jobs with no estimate hours still schedule from quote hours.""" job = _make_job(self.client_obj, self.test_staff, hours=0.0) _set_workshop_hours(job.latest_quote, 8.0) diff --git a/apps/process/tests/test_form_model.py b/apps/process/tests/test_form_model.py index 8c33e3b7d..3134a5f1d 100644 --- a/apps/process/tests/test_form_model.py +++ b/apps/process/tests/test_form_model.py @@ -5,7 +5,7 @@ @pytest.mark.django_db class TestForm: - def test_create_form_definition(self): + def test_create_form_definition(self) -> None: form = Form.objects.create( document_type="form", title="Ladder Inspection Checklist", @@ -15,13 +15,13 @@ def test_create_form_definition(self): assert form.status == "active" assert form.document_type == "form" - def test_filter_by_document_type(self): + def test_filter_by_document_type(self) -> None: Form.objects.create(document_type="form", title="Form") Form.objects.create(document_type="register", title="Reg") assert Form.objects.filter(document_type="form").count() == 1 assert Form.objects.filter(document_type="register").count() == 1 - def test_str_representation(self): + def test_str_representation(self) -> None: doc = Form.objects.create( document_type="form", title="Safety Checklist", @@ -32,7 +32,7 @@ def test_str_representation(self): @pytest.mark.django_db class TestFormEntry: - def test_create_entry(self): + def test_create_entry(self) -> None: doc = Form.objects.create( document_type="register", title="Maintenance Log", @@ -65,7 +65,7 @@ def test_entry_with_job(self, job): assert entry.job == job assert job.form_entries.count() == 1 - def test_cascade_delete(self): + def test_cascade_delete(self) -> None: doc = Form.objects.create( document_type="register", title="Maintenance Log", diff --git a/apps/process/tests/test_form_service.py b/apps/process/tests/test_form_service.py index eb2c813dc..80fe53fe5 100644 --- a/apps/process/tests/test_form_service.py +++ b/apps/process/tests/test_form_service.py @@ -11,7 +11,7 @@ def _make_service(): @pytest.mark.django_db class TestFormServiceCreateEntry: - def test_create_entry_returns_form_entry(self): + def test_create_entry_returns_form_entry(self) -> None: form = Form.objects.create( document_type="form", title="Inspection Form", @@ -36,7 +36,7 @@ def test_create_entry_with_job(self, job): assert entry.job == job - def test_create_entry_with_data(self): + def test_create_entry_with_data(self) -> None: form = Form.objects.create( document_type="form", title="Checklist", @@ -54,7 +54,7 @@ def test_create_entry_with_data(self): @pytest.mark.django_db class TestFormServiceCreateForm: - def test_create_form_happy_path(self): + def test_create_form_happy_path(self) -> None: service = _make_service() doc = service.create_form( title="Inspection Checklist", @@ -71,7 +71,7 @@ def test_create_form_happy_path(self): assert doc.status == "active" assert doc.form_schema == {"fields": [{"key": "item", "type": "text"}]} - def test_create_form_register_type(self): + def test_create_form_register_type(self) -> None: service = _make_service() doc = service.create_form( title="Chemical Register", @@ -80,7 +80,7 @@ def test_create_form_register_type(self): assert doc.document_type == "register" - def test_create_form_rejects_procedure_type(self): + def test_create_form_rejects_procedure_type(self) -> None: service = _make_service() with pytest.raises(ValueError, match="form.*register"): service.create_form( diff --git a/apps/process/tests/test_procedure_model.py b/apps/process/tests/test_procedure_model.py index 9bd32f8d5..88343f5a4 100644 --- a/apps/process/tests/test_procedure_model.py +++ b/apps/process/tests/test_procedure_model.py @@ -5,7 +5,7 @@ @pytest.mark.django_db class TestProcedure: - def test_create_procedure_with_tags(self): + def test_create_procedure_with_tags(self) -> None: doc = Procedure.objects.create( document_type="procedure", title="Drill Press SOP", @@ -16,7 +16,7 @@ def test_create_procedure_with_tags(self): assert "sop" in doc.tags assert doc.status == "active" - def test_filter_by_tags_contains(self): + def test_filter_by_tags_contains(self) -> None: Procedure.objects.create( document_type="procedure", title="SWP1", @@ -31,13 +31,13 @@ def test_filter_by_tags_contains(self): assert swps.count() == 1 assert swps.first().title == "SWP1" - def test_filter_by_document_type(self): + def test_filter_by_document_type(self) -> None: Procedure.objects.create(document_type="procedure", title="Proc") Procedure.objects.create(document_type="reference", title="Ref") assert Procedure.objects.filter(document_type="procedure").count() == 1 assert Procedure.objects.filter(document_type="reference").count() == 1 - def test_str_representation(self): + def test_str_representation(self) -> None: doc = Procedure.objects.create( document_type="procedure", title="MIG Welding", diff --git a/apps/process/tests/test_procedure_service.py b/apps/process/tests/test_procedure_service.py index 9e1834e88..f326a58e2 100644 --- a/apps/process/tests/test_procedure_service.py +++ b/apps/process/tests/test_procedure_service.py @@ -26,7 +26,7 @@ def _create_shop_client(name: str = "Shop Company") -> Company: @pytest.mark.django_db class TestProcedureServiceCreateBlank: - def test_create_blank_procedure_happy_path(self): + def test_create_blank_procedure_happy_path(self) -> None: CompanyDefaults.objects.create( company_name="Morris Sheetmetal", gdrive_reference_library_folder_id="folder-123", @@ -61,7 +61,7 @@ def test_create_blank_procedure_happy_path(self): title="How to weld", folder_id="folder-123" ) - def test_create_blank_procedure_rejects_invalid_type(self): + def test_create_blank_procedure_rejects_invalid_type(self) -> None: service = _make_service() with pytest.raises(ValueError, match="Invalid document_type"): service.create_blank_procedure( @@ -69,7 +69,7 @@ def test_create_blank_procedure_rejects_invalid_type(self): title="Bad type", ) - def test_create_blank_procedure_rejects_missing_folder_config(self): + def test_create_blank_procedure_rejects_missing_folder_config(self) -> None: CompanyDefaults.objects.create( company_name="Test", gdrive_reference_library_folder_id=None, diff --git a/apps/purchasing/tests/test_serializers.py b/apps/purchasing/tests/test_serializers.py index cb7c48b51..03e01f097 100644 --- a/apps/purchasing/tests/test_serializers.py +++ b/apps/purchasing/tests/test_serializers.py @@ -12,7 +12,7 @@ class JobForPurchasingSerializerTests(BaseTestCase): - def test_client_name_uses_related_client_name(self): + def test_client_name_uses_related_client_name(self) -> None: company = Company.objects.create( name="Serializer Company", xero_last_modified=timezone.now(), @@ -31,7 +31,7 @@ def test_client_name_uses_related_client_name(self): class PurchaseOrderDetailSerializerTests(BaseTestCase): - def test_related_display_fields_use_related_objects(self): + def test_related_display_fields_use_related_objects(self) -> None: supplier = Company.objects.create( name="Serializer Supplier", xero_contact_id="00000000-0000-0000-0000-000000000001", @@ -54,7 +54,7 @@ def test_related_display_fields_use_related_objects(self): ) self.assertTrue(data["supplier_has_xero_id"]) - def test_missing_related_display_fields_keep_api_defaults(self): + def test_missing_related_display_fields_keep_api_defaults(self) -> None: purchase_order = PurchaseOrder.objects.create( po_number="PO-SERIALIZER-002", order_date=timezone.localdate(), diff --git a/apps/purchasing/tests/test_stock_fts_search.py b/apps/purchasing/tests/test_stock_fts_search.py index b5fcbd541..d679fcf1a 100644 --- a/apps/purchasing/tests/test_stock_fts_search.py +++ b/apps/purchasing/tests/test_stock_fts_search.py @@ -280,7 +280,7 @@ def test_galvanised_sheet_queries_surface_expected_material(db, query): class TestStockSearchHistoricalRanking(BaseTestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.client_obj = Company.objects.create( name="Stock Search Company", @@ -308,7 +308,7 @@ def _record_material_usage( meta={"item_code": item_code}, ) - def test_unspecified_alloy_prefers_more_frequently_used_variant(self): + def test_unspecified_alloy_prefers_more_frequently_used_variant(self) -> None: preferred = _stock( item_code="SS-304-1.5-1219X2438", description="1.5X1219X2438 3042B SS SHT FIBRE PE", @@ -331,7 +331,7 @@ def test_unspecified_alloy_prefers_more_frequently_used_variant(self): assert preferred.description in _top_descriptions("1.5 stainless") - def test_explicit_alloy_overrides_historical_popularity(self): + def test_explicit_alloy_overrides_historical_popularity(self) -> None: _stock( item_code="SS-304-1.5-1219X2438", description="1.5X1219X2438 3042B SS SHT FIBRE PE", diff --git a/apps/purchasing/tests/test_supplier_search.py b/apps/purchasing/tests/test_supplier_search.py index f1a91b687..7dd67115c 100644 --- a/apps/purchasing/tests/test_supplier_search.py +++ b/apps/purchasing/tests/test_supplier_search.py @@ -65,13 +65,13 @@ def auth_api(db): @pytest.mark.django_db -def test_s_and_t_matches_s_t_supplier_name(): +def test_s_and_t_matches_s_t_supplier_name() -> None: _make_client("S&T Stainless Limited") assert _names("S&T")[0] == "S&T Stainless Limited" -def test_s_and_t_scores_substring_match_above_reversed_initials(): +def test_s_and_t_scores_substring_match_above_reversed_initials() -> None: assert _supplier_name_score( "S&T Stainless Limited", "S&T", @@ -82,7 +82,7 @@ def test_s_and_t_scores_substring_match_above_reversed_initials(): @pytest.mark.django_db -def test_s_and_t_prefers_s_t_supplier_after_broad_single_letter_matches(): +def test_s_and_t_prefers_s_t_supplier_after_broad_single_letter_matches() -> None: for index in range(550): _make_client(f"Stainless Test Distractor {index:03d}") @@ -101,7 +101,7 @@ def test_s_and_t_prefers_s_t_supplier_after_broad_single_letter_matches(): @pytest.mark.django_db -def test_s_and_t_ranks_s_t_before_t_s(): +def test_s_and_t_ranks_s_t_before_t_s() -> None: _make_client("T&S Stainless Ranking Test") _make_client("S&T Stainless Ranking Test") @@ -112,7 +112,7 @@ def test_s_and_t_ranks_s_t_before_t_s(): @pytest.mark.django_db -def test_supplier_alias_matches_attached_client(): +def test_supplier_alias_matches_attached_client() -> None: supplier = _make_client("S&T Stainless Limited") SupplierSearchAlias.objects.create(company=supplier, alias="Steel and Tube") @@ -120,14 +120,14 @@ def test_supplier_alias_matches_attached_client(): @pytest.mark.django_db -def test_allow_jobs_false_does_not_exclude_supplier(): +def test_allow_jobs_false_does_not_exclude_supplier() -> None: _make_client("S&T Stainless Limited", allow_jobs=False) assert _names("S&T")[0] == "S&T Stainless Limited" @pytest.mark.django_db -def test_is_supplier_false_can_outrank_is_supplier_true_with_purchase_history(): +def test_is_supplier_false_can_outrank_is_supplier_true_with_purchase_history() -> None: frequent = _make_client("S&T Stainless Limited", is_supplier=False) _make_client("S&T Stainless Alternate", is_supplier=True) _make_po(frequent) @@ -137,7 +137,7 @@ def test_is_supplier_false_can_outrank_is_supplier_true_with_purchase_history(): @pytest.mark.django_db -def test_archived_and_merged_clients_are_excluded(): +def test_archived_and_merged_clients_are_excluded() -> None: active = _make_client("S&T Exclusion Active") _make_client("S&T Exclusion Archived", xero_archived=True) _make_client("S&T Exclusion Merged", merged_into=active) @@ -146,7 +146,7 @@ def test_archived_and_merged_clients_are_excluded(): @pytest.mark.django_db -def test_recent_purchase_history_boosts_but_old_history_does_not(): +def test_recent_purchase_history_boosts_but_old_history_does_not() -> None: recent = _make_client("Steel Supplier Recent") old = _make_client("Steel Supplier Old") _make_po(recent, days_ago=30) @@ -162,7 +162,7 @@ def test_recent_purchase_history_boosts_but_old_history_does_not(): @pytest.mark.django_db -def test_deleted_purchase_orders_do_not_boost_supplier(): +def test_deleted_purchase_orders_do_not_boost_supplier() -> None: active_po_supplier = _make_client("Steel Supplier Active") deleted_po_supplier = _make_client("Steel Supplier Deleted") _make_po(active_po_supplier) @@ -174,7 +174,7 @@ def test_deleted_purchase_orders_do_not_boost_supplier(): @pytest.mark.django_db -def test_stop_word_only_query_falls_back_to_literal_name_match(): +def test_stop_word_only_query_falls_back_to_literal_name_match() -> None: _make_client("The Tool Shed") _make_client("The Metal Company") diff --git a/apps/quoting/tests/test_pdf_data_validation.py b/apps/quoting/tests/test_pdf_data_validation.py index 013b2e028..7e76097dc 100644 --- a/apps/quoting/tests/test_pdf_data_validation.py +++ b/apps/quoting/tests/test_pdf_data_validation.py @@ -7,7 +7,7 @@ class PDFDataValidationServiceTest(BaseTestCase): """Test cases for PDFDataValidationService.""" - def setUp(self): + def setUp(self) -> None: """Set up test data.""" self.service = PDFDataValidationService() @@ -23,7 +23,7 @@ def setUp(self): supplier=self.supplier, file_name="test_price_list.pdf" ) - def test_validate_extracted_data_valid(self): + def test_validate_extracted_data_valid(self) -> None: """Test validation of valid extracted data.""" data = { "supplier": {"name": "Test Supplier"}, @@ -44,7 +44,7 @@ def test_validate_extracted_data_valid(self): self.assertEqual(len(errors), 0) self.assertEqual(len(warnings), 0) - def test_validate_extracted_data_missing_supplier(self): + def test_validate_extracted_data_missing_supplier(self) -> None: """Test validation with missing supplier name.""" data = { "supplier": {}, @@ -58,7 +58,7 @@ def test_validate_extracted_data_missing_supplier(self): self.assertFalse(is_valid) self.assertIn("Missing supplier name", errors) - def test_validate_extracted_data_no_items(self): + def test_validate_extracted_data_no_items(self) -> None: """Test validation with no items.""" data = {"supplier": {"name": "Test Supplier"}, "items": []} @@ -67,7 +67,7 @@ def test_validate_extracted_data_no_items(self): self.assertTrue(is_valid) # No items is valid, just a warning self.assertIn("No items found in extracted data", warnings) - def test_validate_extracted_data_invalid_items(self): + def test_validate_extracted_data_invalid_items(self) -> None: """Test validation with invalid items.""" data = { "supplier": {"name": "Test Supplier"}, @@ -84,7 +84,7 @@ def test_validate_extracted_data_invalid_items(self): self.assertFalse(is_valid) self.assertIn("No valid items found", errors) - def test_normalize_price_valid_formats(self): + def test_normalize_price_valid_formats(self) -> None: """Test price normalization with various valid formats.""" test_cases = [ ("12.50", 12.50), @@ -104,7 +104,7 @@ def test_normalize_price_valid_formats(self): result = self.service._normalize_price(input_price) self.assertEqual(result, expected) - def test_normalize_price_invalid_formats(self): + def test_normalize_price_invalid_formats(self) -> None: """Test price normalization with invalid formats.""" invalid_prices = ["abc", "12.50.75", "$", "not-a-number"] @@ -113,7 +113,7 @@ def test_normalize_price_invalid_formats(self): with self.assertRaises(ValueError): self.service._normalize_price(invalid_price) - def test_clean_text(self): + def test_clean_text(self) -> None: """Test text cleaning functionality.""" test_cases = [ (" Normal text ", "Normal text"), @@ -130,7 +130,7 @@ def test_clean_text(self): result = self.service._clean_text(input_text) self.assertEqual(result, expected) - def test_sanitize_product_data(self): + def test_sanitize_product_data(self) -> None: """Test product data sanitization.""" products = [ { @@ -164,7 +164,7 @@ def test_sanitize_product_data(self): self.assertEqual(sanitized[1]["product_name"], "Steel Bar") self.assertEqual(sanitized[1]["unit_price"], 15.75) - def test_check_duplicates_no_existing_supplier(self): + def test_check_duplicates_no_existing_supplier(self) -> None: """Test duplicate checking when supplier doesn't exist.""" products = [{"product_name": "New Product", "item_no": "NEW-001"}] @@ -173,7 +173,7 @@ def test_check_duplicates_no_existing_supplier(self): self.assertEqual(len(result["duplicates"]), 0) self.assertEqual(len(result["new"]), 1) - def test_check_duplicates_with_existing_products(self): + def test_check_duplicates_with_existing_products(self) -> None: """Test duplicate checking with existing products.""" # Create existing product SupplierProduct.objects.create( @@ -203,7 +203,7 @@ def test_check_duplicates_with_existing_products(self): self.assertEqual(len(result["new"]), 1) self.assertEqual(result["new"][0]["product_name"], "New Product") - def test_validation_summary(self): + def test_validation_summary(self) -> None: """Test validation summary generation.""" # Run validation that will generate errors and warnings data = { @@ -224,7 +224,7 @@ def test_validation_summary(self): self.assertEqual(summary["warning_count"], 1) self.assertIn("Missing supplier name", summary["errors"]) - def test_long_field_truncation(self): + def test_long_field_truncation(self) -> None: """Test that long fields are properly truncated.""" long_name = "A" * 600 # Longer than 500 char limit long_item_no = "B" * 150 # Longer than 100 char limit @@ -242,7 +242,7 @@ def test_long_field_truncation(self): self.assertEqual(len(sanitized[0]["product_name"]), 500) self.assertEqual(len(sanitized[0]["item_no"]), 100) - def test_variant_id_generation(self): + def test_variant_id_generation(self) -> None: """Test automatic variant_id generation when missing.""" products = [ {"product_name": "Product 1", "description": "First product"}, diff --git a/apps/timesheet/tests/test_daily_timesheet_service.py b/apps/timesheet/tests/test_daily_timesheet_service.py index 0d2d1c5b8..caf25a89a 100644 --- a/apps/timesheet/tests/test_daily_timesheet_service.py +++ b/apps/timesheet/tests/test_daily_timesheet_service.py @@ -13,7 +13,7 @@ class DailyTimesheetServiceTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.target_date = date(2026, 5, 22) self.company = Company.objects.create( @@ -87,7 +87,9 @@ def _create_time_line(self, job: Job, *, hours: str, entry_seq: int) -> CostLine entry_seq=entry_seq, ) - def test_staff_timesheet_data_does_not_lazy_load_job_breakdown_relations(self): + def test_staff_timesheet_data_does_not_lazy_load_job_breakdown_relations( + self, + ) -> None: """Catches N+1 DB access while daily timesheets serialize job/company data.""" other_job = self._create_job( job_number=98767, diff --git a/apps/timesheet/tests/test_payroll_post_api.py b/apps/timesheet/tests/test_payroll_post_api.py index ea5db51db..e1e75b933 100644 --- a/apps/timesheet/tests/test_payroll_post_api.py +++ b/apps/timesheet/tests/test_payroll_post_api.py @@ -13,7 +13,7 @@ class PayrollPostStartApiTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.client_api = APIClient() self.superuser = Staff.objects.create_user( @@ -243,7 +243,7 @@ def test_stream_skips_staff_who_left_before_posted_week( class WeeklyTimesheetApiContractTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() self.client_api = APIClient() self.superuser = Staff.objects.create_user( @@ -256,7 +256,7 @@ def setUp(self): ) self.client_api.force_authenticate(user=self.superuser) - def test_weekly_api_returns_five_days_when_weekends_disabled(self): + def test_weekly_api_returns_five_days_when_weekends_disabled(self) -> None: company = CompanyDefaults.get_solo() company.weekend_timesheets_enabled = False company.save(update_fields=["weekend_timesheets_enabled"]) @@ -274,7 +274,7 @@ def test_weekly_api_returns_five_days_when_weekends_disabled(self): self.assertEqual(payload["start_date"], "2026-05-04") self.assertEqual(payload["end_date"], "2026-05-08") - def test_weekly_api_returns_seven_days_when_weekends_enabled(self): + def test_weekly_api_returns_seven_days_when_weekends_enabled(self) -> None: company = CompanyDefaults.get_solo() company.weekend_timesheets_enabled = True company.save(update_fields=["weekend_timesheets_enabled"]) diff --git a/apps/timesheet/tests/test_permissions.py b/apps/timesheet/tests/test_permissions.py index 8646f247c..492f88854 100644 --- a/apps/timesheet/tests/test_permissions.py +++ b/apps/timesheet/tests/test_permissions.py @@ -11,7 +11,7 @@ class TimesheetPermissionTests(BaseTestCase): """Test that timesheet endpoints require superuser access.""" - def setUp(self): + def setUp(self) -> None: self.factory = RequestFactory() self.client_api = APIClient() @@ -32,39 +32,39 @@ def setUp(self): is_office_staff=True, ) - def test_weekly_timesheet_blocked_for_normal_user(self): + def test_weekly_timesheet_blocked_for_normal_user(self) -> None: self.client_api.force_authenticate(user=self.normal_user) response = self.client_api.get("/api/timesheets/weekly/") self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_weekly_timesheet_allowed_for_superuser(self): + def test_weekly_timesheet_allowed_for_superuser(self) -> None: self.client_api.force_authenticate(user=self.superuser) response = self.client_api.get("/api/timesheets/weekly/") self.assertNotEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_daily_summary_blocked_for_normal_user(self): + def test_daily_summary_blocked_for_normal_user(self) -> None: self.client_api.force_authenticate(user=self.normal_user) response = self.client_api.get("/api/timesheets/daily/2026-04-01/") self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_staff_daily_detail_blocked_for_normal_user(self): + def test_staff_daily_detail_blocked_for_normal_user(self) -> None: self.client_api.force_authenticate(user=self.normal_user) response = self.client_api.get( f"/api/timesheets/staff/{self.superuser.id}/daily/2026-04-01/" ) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_staff_list_blocked_for_normal_user(self): + def test_staff_list_blocked_for_normal_user(self) -> None: self.client_api.force_authenticate(user=self.normal_user) response = self.client_api.get("/api/timesheets/staff/") self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_jobs_list_blocked_for_normal_user(self): + def test_jobs_list_blocked_for_normal_user(self) -> None: self.client_api.force_authenticate(user=self.normal_user) response = self.client_api.get("/api/timesheets/jobs/") self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_payroll_endpoints_blocked_for_normal_user(self): + def test_payroll_endpoints_blocked_for_normal_user(self) -> None: self.client_api.force_authenticate(user=self.normal_user) # Post week to Xero response = self.client_api.post("/api/timesheets/payroll/post-staff-week/") @@ -79,7 +79,7 @@ def test_payroll_endpoints_blocked_for_normal_user(self): response = self.client_api.get("/api/timesheets/payroll/pay-runs/") self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - def test_stream_payroll_blocked_for_normal_user(self): + def test_stream_payroll_blocked_for_normal_user(self) -> None: # stream_payroll_post is a plain Django view, not DRF — use session auth self.client.force_login(self.normal_user) response = self.client.get( diff --git a/apps/timesheet/tests/test_weekly_timesheet_service.py b/apps/timesheet/tests/test_weekly_timesheet_service.py index ef0600c03..8c78ca529 100644 --- a/apps/timesheet/tests/test_weekly_timesheet_service.py +++ b/apps/timesheet/tests/test_weekly_timesheet_service.py @@ -12,7 +12,7 @@ class WeeklyTimesheetServiceCostTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: super().setUp() company = CompanyDefaults.get_solo() company.annual_leave_loading = Decimal("20.00") @@ -47,7 +47,7 @@ def setUp(self): ) self.job.labour_rates.update(charge_out_rate=Decimal("120.00")) - def test_weekly_cash_and_loaded_costs_use_annual_leave_loading(self): + def test_weekly_cash_and_loaded_costs_use_annual_leave_loading(self) -> None: week_start = date(2025, 5, 5) for day_offset in range(5): CostLine.objects.create( diff --git a/apps/workflow/tests/test_api_schema_coverage.py b/apps/workflow/tests/test_api_schema_coverage.py index 9b82dc953..86e705ec0 100644 --- a/apps/workflow/tests/test_api_schema_coverage.py +++ b/apps/workflow/tests/test_api_schema_coverage.py @@ -112,7 +112,7 @@ def _get_schema_paths(self) -> set[str]: ) return {path.lstrip("/").rstrip("/") for path in paths} - def test_all_api_endpoints_in_schema(self): + def test_all_api_endpoints_in_schema(self) -> None: """Every API endpoint must be documented in the OpenAPI schema.""" all_patterns = self._get_all_url_patterns() schema_paths = self._get_schema_paths() diff --git a/apps/workflow/tests/test_company_defaults_api.py b/apps/workflow/tests/test_company_defaults_api.py index b81fa1fe5..c5ccca580 100644 --- a/apps/workflow/tests/test_company_defaults_api.py +++ b/apps/workflow/tests/test_company_defaults_api.py @@ -10,18 +10,18 @@ class CompanyDefaultsAPITests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: self.client = APIClient() self.client.force_authenticate(user=self.test_staff) - def test_get_returns_shop_company_fk_without_name_alias(self): + def test_get_returns_shop_company_fk_without_name_alias(self) -> None: response = self.client.get("/api/company-defaults/") self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn("shop_company", response.data) self.assertNotIn("shop_company_name", response.data) - def test_get_does_not_query_company_for_shop_company_display_name(self): + def test_get_does_not_query_company_for_shop_company_display_name(self) -> None: with CaptureQueriesContext(connection) as captured: response = self.client.get("/api/company-defaults/") diff --git a/apps/workflow/tests/test_company_defaults_schema.py b/apps/workflow/tests/test_company_defaults_schema.py index a85f4c5c9..13df43769 100644 --- a/apps/workflow/tests/test_company_defaults_schema.py +++ b/apps/workflow/tests/test_company_defaults_schema.py @@ -21,7 +21,7 @@ class SettingsMetadataTests(TestCase): """Test settings metadata utilities.""" - def test_all_fields_have_sections(self): + def test_all_fields_have_sections(self) -> None: """Every CompanyDefaults field must have a section assigned.""" model = CompanyDefaults missing = [] @@ -39,7 +39,7 @@ def test_all_fields_have_sections(self): f"Add them to COMPANY_DEFAULTS_FIELD_SECTIONS.", ) - def test_all_sections_are_valid(self): + def test_all_sections_are_valid(self) -> None: """All section keys in mapping must be valid SettingsSection keys.""" valid_keys = {s[0] for s in SettingsSection.all_sections()} @@ -50,32 +50,32 @@ def test_all_sections_are_valid(self): f"Field '{field_name}' has invalid section '{section_key}'", ) - def test_ui_type_mapping_char_field(self): + def test_ui_type_mapping_char_field(self) -> None: """Test CharField maps to 'text' UI type.""" char_field = models.CharField(max_length=100) self.assertEqual(get_ui_type_for_field(char_field), "text") - def test_ui_type_mapping_boolean_field(self): + def test_ui_type_mapping_boolean_field(self) -> None: """Test BooleanField maps to 'boolean' UI type.""" bool_field = models.BooleanField() self.assertEqual(get_ui_type_for_field(bool_field), "boolean") - def test_ui_type_mapping_decimal_field(self): + def test_ui_type_mapping_decimal_field(self) -> None: """Test DecimalField maps to 'number' UI type.""" decimal_field = models.DecimalField(max_digits=5, decimal_places=2) self.assertEqual(get_ui_type_for_field(decimal_field), "number") - def test_ui_type_mapping_time_field(self): + def test_ui_type_mapping_time_field(self) -> None: """Test TimeField maps to 'time' UI type.""" time_field = models.TimeField() self.assertEqual(get_ui_type_for_field(time_field), "time") - def test_ui_type_mapping_url_field(self): + def test_ui_type_mapping_url_field(self) -> None: """Test URLField maps to 'url' UI type.""" url_field = models.URLField() self.assertEqual(get_ui_type_for_field(url_field), "url") - def test_get_field_metadata_structure(self): + def test_get_field_metadata_structure(self) -> None: """Test that get_field_metadata returns expected structure.""" char_field = models.CharField( max_length=100, @@ -94,7 +94,7 @@ def test_get_field_metadata_structure(self): self.assertEqual(metadata["help_text"], "Test help text") self.assertIn("section", metadata) - def test_settings_section_all_sections(self): + def test_settings_section_all_sections(self) -> None: """Test SettingsSection.all_sections() returns expected sections.""" sections = SettingsSection.all_sections() @@ -108,7 +108,7 @@ def test_settings_section_all_sections(self): self.assertIsInstance(section[1], str) # title self.assertIsInstance(section[2], int) # order - def test_settings_section_get_section_info(self): + def test_settings_section_get_section_info(self) -> None: """Test SettingsSection.get_section_info() returns correct info.""" info = SettingsSection.get_section_info("company") self.assertIsNotNone(info) @@ -123,7 +123,7 @@ def test_settings_section_get_section_info(self): class CompanyDefaultsSchemaAPITests(BaseTestCase): """Test the schema API endpoint.""" - def setUp(self): + def setUp(self) -> None: self.client = APIClient() self.staff = Staff.objects.create_user( email="test@example.com", @@ -132,7 +132,7 @@ def setUp(self): last_name="User", ) - def test_schema_endpoint_returns_sections(self): + def test_schema_endpoint_returns_sections(self) -> None: """GET /api/company-defaults/schema/ returns section structure.""" self.client.force_authenticate(user=self.staff) response = self.client.get("/api/company-defaults/schema/") @@ -141,7 +141,7 @@ def test_schema_endpoint_returns_sections(self): self.assertIn("sections", response.data) self.assertIsInstance(response.data["sections"], list) - def test_schema_sections_have_required_keys(self): + def test_schema_sections_have_required_keys(self) -> None: """Each section has key, title, order, and fields.""" self.client.force_authenticate(user=self.staff) response = self.client.get("/api/company-defaults/schema/") @@ -152,7 +152,7 @@ def test_schema_sections_have_required_keys(self): self.assertIn("order", section) self.assertIn("fields", section) - def test_schema_fields_have_required_keys(self): + def test_schema_fields_have_required_keys(self) -> None: """Each field has key, label, type, required, section.""" self.client.force_authenticate(user=self.staff) response = self.client.get("/api/company-defaults/schema/") @@ -165,7 +165,7 @@ def test_schema_fields_have_required_keys(self): self.assertIn("required", field) self.assertIn("section", field) - def test_internal_fields_excluded(self): + def test_internal_fields_excluded(self) -> None: """Internal fields like created_at are not in response.""" self.client.force_authenticate(user=self.staff) response = self.client.get("/api/company-defaults/schema/") @@ -178,7 +178,7 @@ def test_internal_fields_excluded(self): self.assertNotIn("updated_at", all_field_keys) self.assertNotIn("is_primary", all_field_keys) - def test_sections_are_ordered(self): + def test_sections_are_ordered(self) -> None: """Sections are returned in order.""" self.client.force_authenticate(user=self.staff) response = self.client.get("/api/company-defaults/schema/") @@ -186,13 +186,13 @@ def test_sections_are_ordered(self): orders = [s["order"] for s in response.data["sections"]] self.assertEqual(orders, sorted(orders)) - def test_requires_authentication(self): + def test_requires_authentication(self) -> None: """Unauthenticated requests are rejected.""" response = self.client.get("/api/company-defaults/schema/") self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) - def test_expected_sections_present(self): + def test_expected_sections_present(self) -> None: """Expected sections are present in response.""" self.client.force_authenticate(user=self.staff) response = self.client.get("/api/company-defaults/schema/") @@ -210,7 +210,7 @@ def test_expected_sections_present(self): for expected in expected_sections: self.assertIn(expected, section_keys, f"Section '{expected}' missing") - def test_company_section_has_company_name(self): + def test_company_section_has_company_name(self) -> None: """Company section includes company_name field.""" self.client.force_authenticate(user=self.staff) response = self.client.get("/api/company-defaults/schema/") diff --git a/apps/workflow/tests/test_dev_demo_export.py b/apps/workflow/tests/test_dev_demo_export.py index 71d8a09d4..f94bfbaed 100644 --- a/apps/workflow/tests/test_dev_demo_export.py +++ b/apps/workflow/tests/test_dev_demo_export.py @@ -35,7 +35,7 @@ @pytest.mark.django_db -def test_dev_demo_scrub_preserves_business_signal_and_redacts_risk(): +def test_dev_demo_scrub_preserves_business_signal_and_redacts_risk() -> None: staff = Staff.objects.create_user( email="demo.staff@example.test", password="password", @@ -237,7 +237,7 @@ def test_dev_demo_scrub_preserves_business_signal_and_redacts_risk(): assert slip.raw_json == {} -def test_export_dev_demo_dump_refuses_non_dev_source_db(): +def test_export_dev_demo_dump_refuses_non_dev_source_db() -> None: with patch.dict(settings.DATABASES["default"], {"NAME": "dw_msm_prod"}): with pytest.raises(RuntimeError, match="must end in '_dev'"): call_command("export_dev_demo_dump") diff --git a/apps/workflow/tests/test_localdate_regression.py b/apps/workflow/tests/test_localdate_regression.py index 5e1d43d64..7423e1a4e 100644 --- a/apps/workflow/tests/test_localdate_regression.py +++ b/apps/workflow/tests/test_localdate_regression.py @@ -43,7 +43,7 @@ def _make_job(company, staff, name="Localdate Test Job", **extra): class FreezeTimeSanityTests(TestCase): """Belt-and-braces: confirm freeze_time + Pacific/Auckland disagree as expected.""" - def test_utc_and_nz_disagree_on_the_chosen_moment(self): + def test_utc_and_nz_disagree_on_the_chosen_moment(self) -> None: with freeze_time(FROZEN_UTC_MOMENT): # This assertion exists to prove the UTC/NZ-disagree premise that # every other test in this file relies on. The suppression that @@ -55,7 +55,7 @@ def test_utc_and_nz_disagree_on_the_chosen_moment(self): class WorkshopServiceLocalDateTests(TestCase): - def test_resolve_entry_date_returns_nz_date_when_no_param(self): + def test_resolve_entry_date_returns_nz_date_when_no_param(self) -> None: from apps.job.services.workshop_service import WorkshopTimesheetService with freeze_time(FROZEN_UTC_MOMENT): @@ -65,7 +65,7 @@ def test_resolve_entry_date_returns_nz_date_when_no_param(self): class PurchasingValidDateTests(TestCase): - def test_get_valid_date_returns_nz_date_when_value_falsy(self): + def test_get_valid_date_returns_nz_date_when_value_falsy(self) -> None: from apps.purchasing.services.purchasing_rest_service import ( PurchasingRestService, ) @@ -75,7 +75,7 @@ def test_get_valid_date_returns_nz_date_when_value_falsy(self): self.assertEqual(result, NZ_DATE) - def test_get_valid_date_returns_nz_date_when_value_invalid_string(self): + def test_get_valid_date_returns_nz_date_when_value_invalid_string(self) -> None: from apps.purchasing.services.purchasing_rest_service import ( PurchasingRestService, ) @@ -85,7 +85,7 @@ def test_get_valid_date_returns_nz_date_when_value_invalid_string(self): self.assertEqual(result, NZ_DATE) - def test_get_valid_date_returns_nz_date_when_value_wrong_type(self): + def test_get_valid_date_returns_nz_date_when_value_wrong_type(self) -> None: from apps.purchasing.services.purchasing_rest_service import ( PurchasingRestService, ) @@ -104,7 +104,7 @@ class StaffActiveOnDateTests(BaseTestCase): last day. """ - def test_is_currently_active_returns_false_on_their_last_day(self): + def test_is_currently_active_returns_false_on_their_last_day(self) -> None: from apps.accounts.models import Staff staff = Staff( @@ -117,7 +117,7 @@ def test_is_currently_active_returns_false_on_their_last_day(self): with freeze_time(FROZEN_UTC_MOMENT): self.assertFalse(staff.is_currently_active) - def test_currently_active_queryset_excludes_staff_who_left_today(self): + def test_currently_active_queryset_excludes_staff_who_left_today(self) -> None: from apps.accounts.models import Staff staff = Staff.objects.create_user( @@ -171,7 +171,7 @@ def _make_aged_job(self): job.refresh_from_db() return job - def test_calculate_time_in_status_uses_localdate_both_sides(self): + def test_calculate_time_in_status_uses_localdate_both_sides(self) -> None: from apps.accounting.services.core import JobAgingService job = self._make_aged_job() @@ -181,7 +181,7 @@ def test_calculate_time_in_status_uses_localdate_both_sides(self): self.assertEqual(days, 3) - def test_get_timing_data_created_days_ago_uses_localdate_both_sides(self): + def test_get_timing_data_created_days_ago_uses_localdate_both_sides(self) -> None: """Covers core.py:955 (`created_at.date()`) and :959 (`now.date()`). `created_at` UTC midnight April 25 = NZ noon April 25 (both dates @@ -199,7 +199,7 @@ def test_get_timing_data_created_days_ago_uses_localdate_both_sides(self): self.assertEqual(timing["created_date"], "2026-04-25") self.assertEqual(timing["created_days_ago"], 3) - def test_get_last_activity_days_ago_uses_localdate(self): + def test_get_last_activity_days_ago_uses_localdate(self) -> None: """Covers core.py:1145 (`now.date() - activity_date_obj`). The job's most recent activity is its `updated_at`. We pin updated_at @@ -234,7 +234,7 @@ def _make_manager(self, *, is_account_customer): ) return XeroInvoiceManager(company=company, job=job, staff=self.test_staff) - def test_build_payload_uses_nz_local_date(self): + def test_build_payload_uses_nz_local_date(self) -> None: manager = self._make_manager(is_account_customer=False) with ( @@ -247,7 +247,7 @@ def test_build_payload_uses_nz_local_date(self): self.assertEqual(payload.date, NZ_DATE) - def test_account_customer_due_date_is_20th_of_next_month(self): + def test_account_customer_due_date_is_20th_of_next_month(self) -> None: """`Company.is_account_customer=True` → due on the 20th of next month.""" manager = self._make_manager(is_account_customer=True) @@ -262,7 +262,7 @@ def test_account_customer_due_date_is_20th_of_next_month(self): # NZ "today" is 2026-04-28; 20th of next month = 2026-05-20. self.assertEqual(payload.due_date, datetime.date(2026, 5, 20)) - def test_cash_customer_due_date_is_same_day(self): + def test_cash_customer_due_date_is_same_day(self) -> None: """`Company.is_account_customer=False` → due same-day.""" manager = self._make_manager(is_account_customer=False) @@ -277,7 +277,7 @@ def test_cash_customer_due_date_is_same_day(self): self.assertEqual(payload.due_date, NZ_DATE) self.assertEqual(payload.date, payload.due_date) - def test_account_customer_due_date_at_31_day_month_boundary(self): + def test_account_customer_due_date_at_31_day_month_boundary(self) -> None: """The old `(today + 30d).replace(day=20)` formula returned *this* month's 20th when today was the 1st of a 31-day month (Jan, Mar, May, Jul, Aug, Oct, Dec). E.g. on May 1, +30d = May 31 → May 20, @@ -297,7 +297,7 @@ def test_account_customer_due_date_at_31_day_month_boundary(self): self.assertEqual(payload.date, datetime.date(2026, 5, 1)) self.assertEqual(payload.due_date, datetime.date(2026, 6, 20)) - def test_account_customer_due_date_rolls_over_year_in_december(self): + def test_account_customer_due_date_rolls_over_year_in_december(self) -> None: """December → January next year, day 20.""" manager = self._make_manager(is_account_customer=True) @@ -318,7 +318,7 @@ def test_account_customer_due_date_rolls_over_year_in_december(self): class XeroQuoteLocalDateTests(BaseTestCase): """Same as invoice, for quotes.""" - def test_build_payload_uses_nz_local_date(self): + def test_build_payload_uses_nz_local_date(self) -> None: from apps.workflow.views.xero.xero_quote_manager import XeroQuoteManager company = _make_client("Xero Quote Test Company") @@ -348,7 +348,7 @@ class StockServiceAccountingDateTests(BaseTestCase): A material consumed at NZ-morning currently lands on yesterday's books. """ - def test_consume_creates_cost_line_with_nz_local_accounting_date(self): + def test_consume_creates_cost_line_with_nz_local_accounting_date(self) -> None: from apps.purchasing.models import Stock from apps.purchasing.services.stock_service import consume_stock @@ -377,7 +377,7 @@ class DataQualityReportLocalDateTests(BaseTestCase): """The "archived_date" column in the data-quality report should report the NZ calendar date the job was last touched, not the UTC date.""" - def test_archived_date_uses_nz_local(self): + def test_archived_date_uses_nz_local(self) -> None: from apps.job.models import Job from apps.job.services.data_quality_report import ( ArchivedJobsComplianceService, diff --git a/apps/workflow/tests/test_search_telemetry.py b/apps/workflow/tests/test_search_telemetry.py index a08f07c6f..8af911039 100644 --- a/apps/workflow/tests/test_search_telemetry.py +++ b/apps/workflow/tests/test_search_telemetry.py @@ -50,7 +50,7 @@ def test_search_click_endpoint_records_generic_event(db): @pytest.mark.django_db -def test_search_telemetry_caps_displayed_results_at_100(): +def test_search_telemetry_caps_displayed_results_at_100() -> None: yielded_count = 0 def result_ids(): diff --git a/apps/workflow/tests/test_seed_xero_from_database.py b/apps/workflow/tests/test_seed_xero_from_database.py index e45192ba7..19d38e247 100644 --- a/apps/workflow/tests/test_seed_xero_from_database.py +++ b/apps/workflow/tests/test_seed_xero_from_database.py @@ -23,7 +23,7 @@ class ClearProductionXeroIdsTests(TestCase): - def test_refuses_when_db_name_ends_with_prod(self): + def test_refuses_when_db_name_ends_with_prod(self) -> None: """Catastrophic-regression guard: if the configured DB name ends with ``_prod``, ``clear_production_xero_ids`` must not touch the DB. Wiping live ``xero_contact_id``s breaks Xero diff --git a/apps/workflow/tests/test_sync_clients.py b/apps/workflow/tests/test_sync_clients.py index faa8e7f65..fba52e6ab 100644 --- a/apps/workflow/tests/test_sync_clients.py +++ b/apps/workflow/tests/test_sync_clients.py @@ -158,7 +158,7 @@ class SyncClientsArchivedContactTests(TestCase): the same name. sync_companies must handle both without crashing. """ - def setUp(self): + def setUp(self) -> None: self.active_xero_id = "9568adbc-aaaa-bbbb-cccc-000000000001" self.archived_xero_id = "17aa5e1e-aaaa-bbbb-cccc-000000000002" self.company_name = "Powder Coating Group NZ Limited" diff --git a/apps/workflow/tests/test_xero_app_api.py b/apps/workflow/tests/test_xero_app_api.py index 65ef55f22..089654762 100644 --- a/apps/workflow/tests/test_xero_app_api.py +++ b/apps/workflow/tests/test_xero_app_api.py @@ -35,11 +35,11 @@ def _office_staff(email="office@example.test"): class XeroAppApiPermissionTests(APITestCase): - def test_anonymous_forbidden_on_list(self): + def test_anonymous_forbidden_on_list(self) -> None: response = self.client.get("/api/workflow/xero-apps/") self.assertIn(response.status_code, (401, 403)) - def test_anonymous_forbidden_on_create(self): + def test_anonymous_forbidden_on_create(self) -> None: response = self.client.post( "/api/workflow/xero-apps/", { @@ -52,7 +52,7 @@ def test_anonymous_forbidden_on_create(self): ) self.assertIn(response.status_code, (401, 403)) - def test_non_office_staff_forbidden(self): + def test_non_office_staff_forbidden(self) -> None: worker = Staff.objects.create_user( email="worker@example.test", password="x", @@ -67,12 +67,12 @@ def test_non_office_staff_forbidden(self): class XeroAppApiListTests(APITestCase): - def setUp(self): + def setUp(self) -> None: self.client = APIClient() self.user = _office_staff() self.client.force_authenticate(self.user) - def test_list_returns_safe_fields_only(self): + def test_list_returns_safe_fields_only(self) -> None: expires = datetime.now(dt_timezone.utc) + timedelta(hours=1) _row( client_id="c-a", @@ -102,12 +102,12 @@ def test_list_returns_safe_fields_only(self): class XeroAppApiCreateTests(APITestCase): - def setUp(self): + def setUp(self) -> None: self.client = APIClient() self.user = _office_staff() self.client.force_authenticate(self.user) - def test_create_minimal_row(self): + def test_create_minimal_row(self) -> None: payload = { "label": "Backup", "client_id": "c-b", @@ -123,7 +123,7 @@ def test_create_minimal_row(self): self.assertEqual(row.client_secret, "s-b") self.assertEqual(row.webhook_key, "wk-b") - def test_create_duplicate_client_id_returns_400(self): + def test_create_duplicate_client_id_returns_400(self) -> None: _row(client_id="c-a") payload = { "label": "Dup", @@ -135,7 +135,7 @@ def test_create_duplicate_client_id_returns_400(self): response = self.client.post("/api/workflow/xero-apps/", payload, format="json") self.assertEqual(response.status_code, 400) - def test_create_without_secret_rejected(self): + def test_create_without_secret_rejected(self) -> None: # A row created without client_secret can never complete OAuth — # serializer must reject it on create even though secret is # write-only and otherwise tolerated as missing. @@ -150,7 +150,7 @@ def test_create_without_secret_rejected(self): self.assertIn("client_secret", response.data) self.assertFalse(XeroApp.objects.filter(client_id="c-no-secret").exists()) - def test_create_without_webhook_key_rejected(self): + def test_create_without_webhook_key_rejected(self) -> None: # A row without webhook_key would 401 every webhook delivery from # this app's tenant — symmetrical to the missing-client_secret # case, and just as fatal. @@ -165,7 +165,7 @@ def test_create_without_webhook_key_rejected(self): self.assertIn("webhook_key", response.data) self.assertFalse(XeroApp.objects.filter(client_id="c-no-hook").exists()) - def test_patch_without_secret_allowed(self): + def test_patch_without_secret_allowed(self) -> None: # PATCH must NOT require client_secret — the secret is already # persisted, and forcing operators to re-supply it on every label # tweak would be punitive. @@ -182,12 +182,12 @@ def test_patch_without_secret_allowed(self): class XeroAppApiPatchTests(APITestCase): - def setUp(self): + def setUp(self) -> None: self.client = APIClient() self.user = _office_staff() self.client.force_authenticate(self.user) - def test_patch_label_only_does_not_wipe_tokens(self): + def test_patch_label_only_does_not_wipe_tokens(self) -> None: expires = datetime.now(dt_timezone.utc) + timedelta(hours=1) row = _row( client_id="c-a", @@ -206,7 +206,7 @@ def test_patch_label_only_does_not_wipe_tokens(self): self.assertEqual(row.refresh_token, "rrr") self.assertEqual(row.day_remaining, 42) - def test_patch_client_id_wipes_tokens_and_quota(self): + def test_patch_client_id_wipes_tokens_and_quota(self) -> None: expires = datetime.now(dt_timezone.utc) + timedelta(hours=1) row = _row( client_id="c-a", @@ -230,7 +230,7 @@ def test_patch_client_id_wipes_tokens_and_quota(self): self.assertIsNone(row.day_remaining) self.assertIsNone(row.snapshot_at) - def test_patch_active_row_credentials_invalidates_singleton(self): + def test_patch_active_row_credentials_invalidates_singleton(self) -> None: # When the *active* row's credentials change, the in-process # ApiClient singleton is bound to the old client_id/secret. Without # a reset its next call would use stale credentials. Sibling @@ -253,7 +253,7 @@ def test_patch_active_row_credentials_invalidates_singleton(self): mock_reset.assert_called_once() mock_restart.assert_called_once() - def test_patch_inactive_row_credentials_does_not_restart(self): + def test_patch_inactive_row_credentials_does_not_restart(self) -> None: # PATCHing a non-active row's credentials must not touch the # singleton or restart workers — they're bound to the active row, # which is unchanged. @@ -275,7 +275,7 @@ def test_patch_inactive_row_credentials_does_not_restart(self): mock_reset.assert_not_called() mock_restart.assert_not_called() - def test_patch_label_only_does_not_restart(self): + def test_patch_label_only_does_not_restart(self) -> None: # Label change must not propagate as a credential rotation. row = _row(client_id="c-a", is_active=True) with ( @@ -297,18 +297,18 @@ def test_patch_label_only_does_not_restart(self): class XeroAppApiDeleteTests(APITestCase): - def setUp(self): + def setUp(self) -> None: self.client = APIClient() self.user = _office_staff() self.client.force_authenticate(self.user) - def test_delete_inactive_row_succeeds(self): + def test_delete_inactive_row_succeeds(self) -> None: row = _row(client_id="c-a", is_active=False) response = self.client.delete(f"/api/workflow/xero-apps/{row.id}/") self.assertEqual(response.status_code, 204) self.assertFalse(XeroApp.objects.filter(id=row.id).exists()) - def test_delete_active_row_refused(self): + def test_delete_active_row_refused(self) -> None: row = _row(client_id="c-a", is_active=True) response = self.client.delete(f"/api/workflow/xero-apps/{row.id}/") self.assertEqual(response.status_code, 400) @@ -316,12 +316,12 @@ def test_delete_active_row_refused(self): class XeroAppApiActivateTests(APITestCase): - def setUp(self): + def setUp(self) -> None: self.client = APIClient() self.user = _office_staff() self.client.force_authenticate(self.user) - def test_activate_swaps(self): + def test_activate_swaps(self) -> None: a = _row(client_id="c-a", is_active=True) b = _row(client_id="c-b", is_active=False) response = self.client.post(f"/api/workflow/xero-apps/{b.id}/activate/") @@ -331,6 +331,6 @@ def test_activate_swaps(self): self.assertFalse(a.is_active) self.assertTrue(b.is_active) - def test_activate_unknown_id_404(self): + def test_activate_unknown_id_404(self) -> None: response = self.client.post(f"/api/workflow/xero-apps/{uuid.uuid4()}/activate/") self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) diff --git a/apps/workflow/tests/test_xero_app_model.py b/apps/workflow/tests/test_xero_app_model.py index 63f12b18f..c3dba4913 100644 --- a/apps/workflow/tests/test_xero_app_model.py +++ b/apps/workflow/tests/test_xero_app_model.py @@ -23,7 +23,7 @@ def _row(self, **overrides): defaults.update(overrides) return XeroApp.objects.create(**defaults) - def test_create_minimal_row(self): + def test_create_minimal_row(self) -> None: row = self._row() self.assertEqual(row.label, "Primary") self.assertFalse(row.is_active) @@ -32,24 +32,24 @@ def test_create_minimal_row(self): self.assertIsNone(row.day_remaining) self.assertIsNone(row.snapshot_at) - def test_client_id_unique(self): + def test_client_id_unique(self) -> None: self._row(client_id="abc123", label="A") with self.assertRaises(IntegrityError): with transaction.atomic(): self._row(client_id="abc123", label="B") - def test_at_most_one_active_row(self): + def test_at_most_one_active_row(self) -> None: self._row(client_id="abc1", label="A", is_active=True) with self.assertRaises(IntegrityError): with transaction.atomic(): self._row(client_id="abc2", label="B", is_active=True) - def test_two_inactive_rows_allowed(self): + def test_two_inactive_rows_allowed(self) -> None: self._row(client_id="abc1", label="A", is_active=False) self._row(client_id="abc2", label="B", is_active=False) self.assertEqual(XeroApp.objects.count(), 2) - def test_can_swap_active_via_two_updates(self): + def test_can_swap_active_via_two_updates(self) -> None: # Real swaps go through swap_active() which clears the old active # row first, but the constraint must permit that pattern. a = self._row(client_id="abc1", label="A", is_active=True) diff --git a/apps/workflow/tests/test_xero_document_raw_json.py b/apps/workflow/tests/test_xero_document_raw_json.py index 0d2183346..74e0d44d6 100644 --- a/apps/workflow/tests/test_xero_document_raw_json.py +++ b/apps/workflow/tests/test_xero_document_raw_json.py @@ -33,7 +33,7 @@ def add_history_note_to_quote(self, external_id, note): class XeroDocumentRawJsonTests(BaseTestCase): - def setUp(self): + def setUp(self) -> None: self.client_obj = Company.objects.create( name="Raw JSON Company", xero_contact_id=str(uuid.uuid4()), @@ -54,7 +54,7 @@ def setUp(self): ) CompanyDefaults.clear_cache() - def test_created_invoice_stores_canonical_raw_json_dict(self): + def test_created_invoice_stores_canonical_raw_json_dict(self) -> None: raw_response = { "_contact": {"_name": "Raw JSON Company"}, "_invoice_id": str(uuid.uuid4()), @@ -95,7 +95,7 @@ def test_created_invoice_stores_canonical_raw_json_dict(self): self.assertEqual(invoice.total_incl_tax, Decimal("115.00")) self.assertEqual(invoice.amount_due, Decimal("115.00")) - def test_created_quote_stores_canonical_raw_json_dict(self): + def test_created_quote_stores_canonical_raw_json_dict(self) -> None: self.job.latest_quote.summary = {"cost": 0.0, "rev": 250.0, "hours": 0.0} self.job.latest_quote.save(update_fields=["summary"]) raw_response = { diff --git a/apps/workflow/tests/test_xero_pay_item.py b/apps/workflow/tests/test_xero_pay_item.py index 62d4b5577..d107bcf8e 100644 --- a/apps/workflow/tests/test_xero_pay_item.py +++ b/apps/workflow/tests/test_xero_pay_item.py @@ -6,7 +6,7 @@ class XeroPayItemLookupTests(TestCase): - def test_get_by_multiplier_prefers_xero_backed_ordinary_time(self): + def test_get_by_multiplier_prefers_xero_backed_ordinary_time(self) -> None: stale = XeroPayItem.objects.create( name="Time and one half (old)", uses_leave_api=False, @@ -25,7 +25,7 @@ def test_get_by_multiplier_prefers_xero_backed_ordinary_time(self): self.assertEqual(XeroPayItem.get_by_multiplier(Decimal("1.00")), ordinary) self.assertNotEqual(XeroPayItem.get_by_multiplier(Decimal("1.00")), stale) - def test_get_by_multiplier_prefers_xero_backed_time_and_half(self): + def test_get_by_multiplier_prefers_xero_backed_time_and_half(self) -> None: XeroPayItem.objects.update_or_create( name="Overtime (1.5)", uses_leave_api=False, diff --git a/apps/workflow/tests/test_xero_po_manager.py b/apps/workflow/tests/test_xero_po_manager.py index d66930aa3..a2e31fdd3 100644 --- a/apps/workflow/tests/test_xero_po_manager.py +++ b/apps/workflow/tests/test_xero_po_manager.py @@ -29,7 +29,7 @@ class XeroPurchaseOrderManagerConstructionTests(BaseAPITestCase): @classmethod - def setUpTestData(cls): + def setUpTestData(cls) -> None: super().setUpTestData() cls.test_staff.is_office_staff = True cls.test_staff.save(update_fields=["is_office_staff"]) diff --git a/apps/workflow/tests/test_xero_quota_floor.py b/apps/workflow/tests/test_xero_quota_floor.py index 13f3c207f..f67ac9afc 100644 --- a/apps/workflow/tests/test_xero_quota_floor.py +++ b/apps/workflow/tests/test_xero_quota_floor.py @@ -96,28 +96,28 @@ class QuotaFloorBreachedHelperTests(TestCase): useful sync; false negatives burn quota needed for user-triggered invoices. """ - def test_no_active_row_returns_false(self): + def test_no_active_row_returns_false(self) -> None: # Nothing to gate against — fall through and let the call go. self.assertFalse(quota_floor_breached(100)) - def test_missing_snapshot_returns_false(self): + def test_missing_snapshot_returns_false(self) -> None: # Active row exists but no API call has happened yet. _active_app() self.assertFalse(quota_floor_breached(100)) - def test_day_remaining_above_floor_returns_false(self): + def test_day_remaining_above_floor_returns_false(self) -> None: _set_quota(day_remaining=200) self.assertFalse(quota_floor_breached(100)) - def test_day_remaining_at_floor_returns_true(self): + def test_day_remaining_at_floor_returns_true(self) -> None: _set_quota(day_remaining=100) self.assertTrue(quota_floor_breached(100)) - def test_day_remaining_below_floor_returns_true(self): + def test_day_remaining_below_floor_returns_true(self) -> None: _set_quota(day_remaining=50) self.assertTrue(quota_floor_breached(100)) - def test_day_remaining_none_returns_false(self): + def test_day_remaining_none_returns_false(self) -> None: # First-call response sometimes omits day_remaining. _active_app( day_remaining=None, @@ -126,7 +126,7 @@ def test_day_remaining_none_returns_false(self): ) self.assertFalse(quota_floor_breached(100)) - def test_stale_snapshot_returns_false(self): + def test_stale_snapshot_returns_false(self) -> None: # Snapshot older than the staleness window — let the next call # probe Xero fresh; the rolling 24h window has freed quota since. _set_quota(day_remaining=10, snapshot_age_seconds=60 * 60) @@ -166,7 +166,7 @@ def _run_handle_rate_limit( # day-limit branch raises; we don't care about that here. pass - def test_minute_limit_429_writes_snapshot_to_bound_row(self): + def test_minute_limit_429_writes_snapshot_to_bound_row(self) -> None: row = _active_app() with patch("apps.workflow.api.xero.client.time.sleep"): self._run_handle_rate_limit( @@ -180,7 +180,7 @@ def test_minute_limit_429_writes_snapshot_to_bound_row(self): self.assertEqual(row.minute_remaining, 0) self.assertIsNotNone(row.snapshot_at) - def test_day_limit_429_writes_snapshot_and_last_429_at(self): + def test_day_limit_429_writes_snapshot_and_last_429_at(self) -> None: row = _active_app() with patch( "apps.workflow.api.xero.client.persist_app_error", @@ -196,7 +196,7 @@ def test_day_limit_429_writes_snapshot_and_last_429_at(self): self.assertEqual(row.day_remaining, 0) self.assertIsNotNone(row.last_429_at) - def test_writes_to_bound_row_not_active_row(self): + def test_writes_to_bound_row_not_active_row(self) -> None: # Construct a client bound to row B's id while row A is currently # active. The 429 must update B, not A. a = _active_app(client_id="c-a", label="A", is_active=True) @@ -229,7 +229,7 @@ class StoreQuotaSnapshotWritesToBoundRowTests(TestCase): healthy quota while the active worker is actually exhausted. """ - def test_2xx_updates_bound_row(self): + def test_2xx_updates_bound_row(self) -> None: from apps.workflow.api.xero.client import RateLimitedRESTClient row = _active_app() @@ -242,7 +242,7 @@ def test_2xx_updates_bound_row(self): self.assertEqual(row.minute_remaining, 55) self.assertIsNotNone(row.snapshot_at) - def test_no_app_id_silently_skips(self): + def test_no_app_id_silently_skips(self) -> None: from apps.workflow.api.xero.client import RateLimitedRESTClient # Pre-existing row stays untouched when client has no app_id. @@ -254,7 +254,7 @@ def test_no_app_id_silently_skips(self): row.refresh_from_db() self.assertIsNone(row.day_remaining) - def test_both_none_leaves_stored_values_untouched(self): + def test_both_none_leaves_stored_values_untouched(self) -> None: # Token refreshes hit identity.xero.com, which returns no quota # headers — the heartbeat runs every 5 min, so a clobber here means # the badge reads "—" almost all the time. @@ -274,7 +274,7 @@ def test_both_none_leaves_stored_values_untouched(self): self.assertEqual(row.minute_remaining, 58) self.assertEqual(row.snapshot_at, before) - def test_partial_reading_updates_only_present_field(self): + def test_partial_reading_updates_only_present_field(self) -> None: # A minute-limit 429 carries X-MinLimit-Remaining but not the day # header — record the minute count without wiping the day count. from apps.workflow.api.xero.client import RateLimitedRESTClient @@ -301,14 +301,14 @@ class SynchroniseXeroDataOrchestratorGateTests(TestCase): must abort as an operational abort, not report success after doing no work. """ - def setUp(self): + def setUp(self) -> None: cache.delete("xero_sync_lock") _set_company_floor() - def tearDown(self): + def tearDown(self) -> None: cache.delete("xero_sync_lock") - def test_floor_breached_raises_before_pipeline(self): + def test_floor_breached_raises_before_pipeline(self) -> None: # The orchestrator must raise XeroQuotaFloorReached, NOT yield a # warning event and return. A returned generator looks like a # successful empty stream to XeroSyncService.run_sync, which would @@ -334,7 +334,7 @@ def test_floor_breached_raises_before_pipeline(self): mock_deep.assert_not_called() mock_normal.assert_not_called() - def test_floor_breached_does_not_advance_last_sync_timestamps(self): + def test_floor_breached_does_not_advance_last_sync_timestamps(self) -> None: # Business case: a quota abort must not advance last-sync timestamps; # otherwise the next real sync skips work and stale Xero data remains # hidden for days. @@ -356,7 +356,7 @@ class SyncXeroDataPerPageGateTests(TestCase): it consumes quota reserved for user-initiated work. """ - def setUp(self): + def setUp(self) -> None: # Snapshot now lives on XeroApp rows — cleared automatically by # TestCase's per-test transaction rollback. _set_company_floor() @@ -365,7 +365,7 @@ def _consume(self, generator): """Fully iterate the generator and return its emitted events.""" return list(generator) - def test_floor_breached_raises_before_fetch(self): + def test_floor_breached_raises_before_fetch(self) -> None: # Per-page gate must raise (not yield+return). See the orchestrator # test above for the same reasoning re: silent success masking. _set_quota(day_remaining=50) @@ -386,7 +386,7 @@ def test_floor_breached_raises_before_fetch(self): fetch.assert_not_called() self.assertIn("quota at floor", str(ctx.exception)) - def test_above_floor_proceeds_normally(self): + def test_above_floor_proceeds_normally(self) -> None: _set_quota(day_remaining=500) # One page returning fewer than page_size → loop completes after one fetch. page = MagicMock() @@ -419,7 +419,7 @@ class StockBatchedUpsertRefactorTests(TestCase): per item while still preserving the create-vs-update behavior Xero expects. """ - def setUp(self): + def setUp(self) -> None: _set_company_floor() # sync_all_local_stock_to_xero builds AccountingApi from the lazy # auth.api_client singleton, which reads the active XeroApp row on @@ -430,12 +430,12 @@ def setUp(self): auth._reset_api_client() - def tearDown(self): + def tearDown(self) -> None: from apps.workflow.api.xero import auth auth._reset_api_client() - def test_upsert_batch_called_with_mixed_create_and_update_payload(self): + def test_upsert_batch_called_with_mixed_create_and_update_payload(self) -> None: from apps.workflow.api.xero import stock_sync # Two local items: one already in Xero by Code, one brand new. @@ -532,13 +532,13 @@ class RunSyncAbortedBranchTests(TestCase): operational abort, not as a green sync or as pages of duplicate AppErrors. """ - def setUp(self): + def setUp(self) -> None: _shared.delete(SYNC_STATUS_KEY) - def tearDown(self): + def tearDown(self) -> None: _shared.delete(SYNC_STATUS_KEY) - def test_quota_floor_emits_aborted_marker_and_skips_persist_app_error(self): + def test_quota_floor_emits_aborted_marker_and_skips_persist_app_error(self) -> None: from apps.workflow.models import AppError from apps.workflow.tasks import xero_sync_task diff --git a/apps/workflow/tests/test_xero_setup_command.py b/apps/workflow/tests/test_xero_setup_command.py index a33ff0cd4..e30bd6f69 100644 --- a/apps/workflow/tests/test_xero_setup_command.py +++ b/apps/workflow/tests/test_xero_setup_command.py @@ -297,7 +297,7 @@ def test_production_setup_validates_without_creating_xero_items( ], ) - def test_removed_create_missing_xero_items_flag_is_rejected(self): + def test_removed_create_missing_xero_items_flag_is_rejected(self) -> None: parser = Command().create_parser("manage.py", "xero") with self.assertRaises(CommandError): parser.parse_args(["--setup", "--create-missing-xero-items"]) diff --git a/apps/workflow/tests/test_xero_transform_contact_resolution.py b/apps/workflow/tests/test_xero_transform_contact_resolution.py index 09a961451..c559123d3 100644 --- a/apps/workflow/tests/test_xero_transform_contact_resolution.py +++ b/apps/workflow/tests/test_xero_transform_contact_resolution.py @@ -19,7 +19,7 @@ def _make_contact(contact_id: str, **extra): class XeroTransformContactResolutionTests(TestCase): - def setUp(self): + def setUp(self) -> None: self.company = Company.objects.create( name="Existing Company", xero_contact_id="contact-123", diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 94b6f1b0f..924706083 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -377,65 +377,29 @@ apps/job/services/month_end_service.py:0: error: Missing type arguments for gene apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_xero_pay_item.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_pay_item.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_pay_item.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_pay_item.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_model.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_model.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_model.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_model.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_model.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_model.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: note: Use "-> None" if function does not return a value apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -544,26 +508,8 @@ apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase apps/quoting/mcp.py:0: error: Need type annotation for "supplier_prices" (hint: "supplier_prices: dict[, ] = ...") [var-annotated] -apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] -apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_procedure_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_model.py:0: note: Use "-> None" if function does not return a value apps/process/services/form_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/form_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] @@ -657,10 +603,6 @@ apps/accounting/services/wip_service.py:0: error: Incompatible return value type apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -671,22 +613,12 @@ apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a ty apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -903,69 +835,23 @@ apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments f apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1007,8 +893,6 @@ apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a t apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_search_telemetry.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_search_telemetry.py:0: error: Call to untyped function "result_ids" in typed context [no-untyped-call] apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1075,28 +959,6 @@ apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a re apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: note: Use "-> None" if function does not return a value apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1370,98 +1232,30 @@ apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | Non apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Argument "row_date" to "build_row" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "tuple[str, str, int] | None" is not indexable [index] apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "tuple[str, str, int] | None" is not indexable [index] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: Need type annotation for "all_field_keys" (hint: "all_field_keys: list[] = ...") [var-annotated] apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_schema.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_company_defaults_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_api.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_company_defaults_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_company_defaults_api.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/timesheet/tests/test_weekly_timesheet_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_weekly_timesheet_service.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_weekly_timesheet_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_weekly_timesheet_service.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_permissions.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_permissions.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: note: Use "-> None" if function does not return a value apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] @@ -1476,20 +1270,10 @@ apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a ty apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: note: Use "-> None" if function does not return a value apps/timesheet/tests/test_jobs_api_filter.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_daily_timesheet_service.py:0: note: Use "-> None" if function does not return a value apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/tests/test_daily_timesheet_service.py:0: note: Use "-> None" if function does not return a value apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1509,465 +1293,97 @@ apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a v apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests/test_pdf_data_validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_pdf_data_validation.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_workshop_schedule_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_workshop_schedule_api.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_make_special_leave_job" in typed context [no-untyped-call] apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_book_time" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_make_special_leave_job" in typed context [no-untyped-call] apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_book_time" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertGreater" of "TestCase" [misc] apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertGreater" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderGT[Any]" [arg-type] apps/operations/tests/test_scheduler_service.py:0: error: Incompatible type for lookup 'allocation_date': (got "date | None", expected "str | date") [misc] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_set_efficiency" in typed context [no-untyped-call] apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_set_efficiency" in typed context [no-untyped-call] apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertGreater" of "TestCase" [misc] apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertGreater" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderGT[Any]" [arg-type] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertLessEqual" of "TestCase" [misc] apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertLessEqual" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderLE[Any]" [arg-type] apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value -apps/operations/tests/test_scheduler_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_persistence.py:0: note: Use "-> None" if function does not return a value apps/operations/tests/test_scheduler_persistence.py:0: error: Item "None" of "SchedulerRun | None" has no attribute "id" [union-attr] apps/job/tests/test_workshop_timesheet_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/tests/test_workshop_timesheet_api.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_workshop_pdf_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_pdf_goldens.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_pdf_goldens.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_mcp_tool_integration.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_mcp_tool_integration.py:0: error: Missing positional argument "query" in call to "search_products" of "QuotingTool" [call-arg] -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_mcp_tool_integration.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_latest_costsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_latest_costsets.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_latest_costsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_latest_costsets.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_latest_costsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_latest_costsets.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_latest_costsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_latest_costsets.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_latest_costsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_latest_costsets.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_latest_costsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_latest_costsets.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_invoicing.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_invoicing.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_files_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_files_api.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_files_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_files_api.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_files_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_files_api.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_files_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/job/tests/test_job_files_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_files_api.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_costline_schema_validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_chat_api_endpoints.py:0: error: Need type annotation for "data" (hint: "data: dict[, ] = ...") [var-annotated] -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: note: Use "-> None" if function does not return a value apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/crm/tests/test_phone_call_service.py:0: error: Cannot assign to a method [method-assign] @@ -1985,158 +1401,64 @@ apps/company/tests/test_company_merge_service.py:0: error: Value of type "Any | apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/tests/test_staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_staff_api.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_displayable_staff.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_displayable_staff.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_sales_pipeline_api.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] apps/accounting/tests/test_sales_pipeline_api.py:0: error: "type[SalesPipelineAPITests]" has no attribute "office_staff" [attr-defined] apps/accounting/tests/test_sales_pipeline_api.py:0: error: "SalesPipelineAPITests" has no attribute "office_staff" [attr-defined] apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounting/tests/test_sales_pipeline_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_invoice_models.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_models.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a type annotation [no-untyped-def] apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a type annotation [no-untyped-def] apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_core_nplusone.py:0: note: Use "-> None" if function does not return a value apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_core_nplusone.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_core_nplusone.py:0: note: Use "-> None" if function does not return a value apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2218,129 +1540,43 @@ apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_kanban_search.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] @@ -2348,22 +1584,14 @@ apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped functio apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_ordered_names" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_ordered_names" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_ordered_names" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_ordered_names" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] @@ -2372,46 +1600,6 @@ apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineSer apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value -apps/accounting/tests/test_sales_pipeline_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_service.py:0: note: Use "-> None" if function does not return a value apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2675,13 +1863,7 @@ apps/company/views/contact_method_viewset.py:0: error: Missing type arguments fo apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_serializers.py:0: note: Use "-> None" if function does not return a value apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] @@ -2730,10 +1912,6 @@ apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: note: Use "-> None" if function does not return a value -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: note: Use "-> None" if function does not return a value apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2828,14 +2006,8 @@ apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped functio apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: note: Use "-> None" if function does not return a value -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: note: Use "-> None" if function does not return a value apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: note: Use "-> None" if function does not return a value apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2849,10 +2021,6 @@ apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a t apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/job/tests/test_modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_modern_timesheet_views.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_modern_timesheet_views.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2950,159 +2118,55 @@ apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_rest_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_rest_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_event_deduplication.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_event_deduplication.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/tests/test_event_deduplication.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_event_deduplication.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_event_deduplication.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_event_deduplication.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] @@ -3359,105 +2423,25 @@ apps/process/views/procedure_viewsets.py:0: error: Function is missing a type an apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: note: Use "-> None" if function does not return a value apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_quote_modes.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: note: Use "-> None" if function does not return a value apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value -apps/job/tests/test_chat_performance.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_chat_performance.py:0: note: Use "-> None" if function does not return a value apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/auth.py:0: error: Call to untyped function "RateLimitedRESTClient" in typed context [no-untyped-call] @@ -3677,8 +2661,6 @@ apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annot apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -3702,8 +2684,6 @@ apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a t apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] @@ -3898,60 +2878,24 @@ apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped funct apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] @@ -4006,97 +2950,43 @@ apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a typ apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_run_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_run_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_run_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_company_floor" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_company_floor" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_consume" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_consume" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_company_floor" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.api.xero.stock_sync" does not explicitly export attribute "XeroAccount" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_gen" in typed context [no-untyped-call] apps/workflow/tests/test_tasks.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] apps/workflow/tests/test_celery_setup.py:0: error: "Celery" has no attribute "main" [attr-defined] @@ -4107,8 +2997,6 @@ apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_po_manager.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_po_manager.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "supplier" [attr-defined] apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "purchase_order" [attr-defined] @@ -4166,8 +3054,6 @@ apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_seed_xero_from_database.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_seed_xero_from_database.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_seed_xero_from_database.py:0: error: Incompatible types in assignment (expression has type "StringIO", variable has type "OutputWrapper") [assignment] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -4212,16 +3098,8 @@ apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a retu apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value -apps/accounts/tests/test_auth_observability.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: note: Use "-> None" if function does not return a value apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -4240,8 +3118,6 @@ apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped functio apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_leave_names" in typed context [no-untyped-call] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Cannot assign to a method [method-assign] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: note: Use "-> None" if function does not return a value apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] From 1527ab366f1cb00330473f260fe9d30213b24e84 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 10:56:25 +1200 Subject: [PATCH 22/39] KAN-316 test: annotate test factory helpers Type the hot test helpers that drove most no-untyped-call errors in the test baseline. Model-building factories whose callers pass a known set of overrides get Unpack[TypedDict] (the _stock, _row, _client, _job, XeroApp factories); helpers that forward arbitrary model kwargs or pop a non-field key (the phone-pop company builders, _make_job(**extra)) take object as a no-regret fallback that a TypedDict can replace later. Also annotate the production convert_html_to_reportlab (str -> str), which 24 test calls depended on. The baseline sync also records the production fixes from b2cb5edd that had not yet been baseline-synced, so the diff reorders more than this commit's test edits alone. --- .../tests/test_invoice_calculation.py | 10 +- .../tests/test_get_company_for_xero.py | 4 +- apps/job/services/workshop_pdf_service.py | 2 +- apps/job/tests/test_job_event_tracking.py | 5 +- apps/job/tests/test_job_invoicing.py | 10 +- .../job/tests/test_kanban_reorder_priority.py | 4 +- apps/job/tests/test_kanban_service.py | 7 +- .../purchasing/tests/test_stock_fts_search.py | 26 +- .../workflow/tests/test_data_versions_view.py | 54 +- .../tests/test_localdate_regression.py | 23 +- apps/workflow/tests/test_push_contacts.py | 6 +- .../workflow/tests/test_session_replay_api.py | 2 +- apps/workflow/tests/test_xero_app_api.py | 21 +- apps/workflow/tests/test_xero_app_model.py | 14 +- mypy-baseline.txt | 3396 ++++++++--------- 15 files changed, 1671 insertions(+), 1913 deletions(-) diff --git a/apps/accounting/tests/test_invoice_calculation.py b/apps/accounting/tests/test_invoice_calculation.py index 6b20205dd..fd0b2c8fa 100644 --- a/apps/accounting/tests/test_invoice_calculation.py +++ b/apps/accounting/tests/test_invoice_calculation.py @@ -17,7 +17,7 @@ ) from apps.company.models import Company from apps.job.models import Job -from apps.job.models.costing import CostLine +from apps.job.models.costing import CostLine, CostSet from apps.testing import BaseTestCase @@ -30,7 +30,7 @@ def setUp(self) -> None: xero_last_modified=timezone.now(), ) - def _create_job(self, pricing_methodology="time_materials"): + def _create_job(self, pricing_methodology: str = "time_materials") -> Job: job = Job( company=self.client_obj, name="Test Job", @@ -39,7 +39,7 @@ def _create_job(self, pricing_methodology="time_materials"): job.save(staff=self.test_staff) return job - def _add_revenue_line(self, cost_set, revenue): + def _add_revenue_line(self, cost_set: CostSet, revenue: Decimal) -> None: CostLine.objects.create( cost_set=cost_set, kind="adjust", @@ -50,7 +50,9 @@ def _add_revenue_line(self, cost_set, revenue): accounting_date=date.today(), ) - def _create_invoice(self, job, amount, status="AUTHORISED"): + def _create_invoice( + self, job: Job, amount: Decimal, status: str = "AUTHORISED" + ) -> Invoice: return Invoice.objects.create( job=job, company=self.client_obj, diff --git a/apps/company/tests/test_get_company_for_xero.py b/apps/company/tests/test_get_company_for_xero.py index 9893c2452..e06bf0a51 100644 --- a/apps/company/tests/test_get_company_for_xero.py +++ b/apps/company/tests/test_get_company_for_xero.py @@ -18,7 +18,9 @@ class GetCompanyForXeroTests(TestCase): """Pin the wire-format contract independent of which push function consumes it.""" - def _make_company(self, **overrides): + def _make_company(self, **overrides: object) -> Company: + # `object` (not a TypedDict) because callers pass a non-field `phone` + # key that is popped and routed to a ContactMethod, not Company.create(). defaults = { "name": "Acme Ltd", "xero_last_modified": timezone.now(), diff --git a/apps/job/services/workshop_pdf_service.py b/apps/job/services/workshop_pdf_service.py index 8b0f6978d..4ae195898 100644 --- a/apps/job/services/workshop_pdf_service.py +++ b/apps/job/services/workshop_pdf_service.py @@ -595,7 +595,7 @@ def _fit_dimensions( return w * scale, h * scale -def convert_html_to_reportlab(html_content): +def convert_html_to_reportlab(html_content: str) -> str: """ Convert Quill HTML to ReportLab-friendly inline markup, with list support. diff --git a/apps/job/tests/test_job_event_tracking.py b/apps/job/tests/test_job_event_tracking.py index 2a813cf9b..3103b29f8 100644 --- a/apps/job/tests/test_job_event_tracking.py +++ b/apps/job/tests/test_job_event_tracking.py @@ -1,6 +1,7 @@ """Tests for automatic JobEvent tracking via Job.save().""" from datetime import timedelta +from typing import Any from django.contrib.auth import get_user_model from django.test import SimpleTestCase @@ -262,7 +263,7 @@ def test_status_change_with_update_fields_persists_completed_at(self) -> None: class JobEventDescriptionTest(SimpleTestCase): """Pure-Python tests for the computed description property and builders.""" - def _event(self, event_type, detail): + def _event(self, event_type: str, detail: dict[str, Any]) -> JobEvent: return JobEvent(event_type=event_type, detail=detail) def test_description_property_delegates_to_build_description(self) -> None: @@ -548,7 +549,7 @@ def setUp(self) -> None: ) self.xero_pay_item = XeroPayItem.get_ordinary_time() - def _make_job(self, name, status="in_progress"): + def _make_job(self, name: str, status: str = "in_progress") -> Job: job = Job( name=name, company=self.client_obj, diff --git a/apps/job/tests/test_job_invoicing.py b/apps/job/tests/test_job_invoicing.py index 93430193d..13d6f4087 100644 --- a/apps/job/tests/test_job_invoicing.py +++ b/apps/job/tests/test_job_invoicing.py @@ -9,7 +9,7 @@ from apps.accounting.models.invoice import Invoice from apps.company.models import Company from apps.job.models import Job -from apps.job.models.costing import CostLine +from apps.job.models.costing import CostLine, CostSet from apps.job.services.job_service import recalculate_job_invoicing_state from apps.testing import BaseTestCase @@ -23,7 +23,7 @@ def setUp(self) -> None: xero_last_modified=timezone.now(), ) - def _create_job(self, pricing_methodology="time_materials"): + def _create_job(self, pricing_methodology: str = "time_materials") -> Job: """Create a job. Job.save() auto-creates CostSets (actual, quote, estimate).""" job = Job( company=self.client_obj, @@ -33,7 +33,7 @@ def _create_job(self, pricing_methodology="time_materials"): job.save(staff=self.test_staff) return job - def _add_revenue_line(self, cost_set, revenue): + def _add_revenue_line(self, cost_set: CostSet, revenue: Decimal) -> None: """Add a CostLine with the given revenue to an existing CostSet.""" CostLine.objects.create( cost_set=cost_set, @@ -45,7 +45,9 @@ def _add_revenue_line(self, cost_set, revenue): accounting_date=date.today(), ) - def _create_invoice(self, job, amount, status="AUTHORISED"): + def _create_invoice( + self, job: Job, amount: Decimal, status: str = "AUTHORISED" + ) -> Invoice: """Create an invoice for the given job.""" return Invoice.objects.create( job=job, diff --git a/apps/job/tests/test_kanban_reorder_priority.py b/apps/job/tests/test_kanban_reorder_priority.py index 1fb2f89c4..812dc9444 100644 --- a/apps/job/tests/test_kanban_reorder_priority.py +++ b/apps/job/tests/test_kanban_reorder_priority.py @@ -26,7 +26,7 @@ def setUp(self) -> None: ) self.xero_pay_item = XeroPayItem.get_ordinary_time() - def _make_job(self, name, status="in_progress"): + def _make_job(self, name: str, status: str = "in_progress") -> Job: job = Job( name=name, company=self.company, @@ -37,7 +37,7 @@ def _make_job(self, name, status="in_progress"): job.save(staff=self.user) return job - def _ordered_names(self, status="in_progress"): + def _ordered_names(self, status: str = "in_progress") -> list[str]: return list( Job.objects.filter(status=status) .order_by("-priority", "-created_at") diff --git a/apps/job/tests/test_kanban_service.py b/apps/job/tests/test_kanban_service.py index 273cd744e..eb7962498 100644 --- a/apps/job/tests/test_kanban_service.py +++ b/apps/job/tests/test_kanban_service.py @@ -10,6 +10,7 @@ from apps.accounts.models import Staff from apps.company.models import Company, CompanyPersonLink, Person from apps.job.models import Job +from apps.job.models.costing import CostSet from apps.job.services.kanban_service import KanbanService from apps.testing import BaseTestCase from apps.workflow.models import CompanyDefaults @@ -25,7 +26,9 @@ def setUp(self) -> None: ) self.shop_company = CompanyDefaults.get_solo().shop_company - def _create_job(self, pricing_methodology="time_materials", name="Test Job"): + def _create_job( + self, pricing_methodology: str = "time_materials", name: str = "Test Job" + ) -> Job: """Create a job. Job.save() auto-creates CostSets (actual, quote, estimate).""" job = Job( company=self.client_obj, @@ -35,7 +38,7 @@ def _create_job(self, pricing_methodology="time_materials", name="Test Job"): job.save(staff=self.test_staff) return job - def _set_summary_revenue(self, cost_set, revenue): + def _set_summary_revenue(self, cost_set: CostSet, revenue: Decimal) -> None: """Set the precomputed revenue total that serialize_job_for_api reads.""" cost_set.summary = {"rev": float(revenue)} cost_set.save(update_fields=["summary"]) diff --git a/apps/purchasing/tests/test_stock_fts_search.py b/apps/purchasing/tests/test_stock_fts_search.py index d679fcf1a..3adb3c543 100644 --- a/apps/purchasing/tests/test_stock_fts_search.py +++ b/apps/purchasing/tests/test_stock_fts_search.py @@ -10,6 +10,7 @@ from datetime import date from decimal import Decimal +from typing import TypedDict, Unpack import pytest from django.utils import timezone @@ -29,13 +30,24 @@ from apps.workflow.models import CompanyDefaults, SearchTelemetryEvent -def _stock(**overrides): - defaults = dict( - description="Generic material", - quantity=Decimal("1.00"), - unit_cost=Decimal("10.00"), - is_active=True, - ) +class _StockOverrides(TypedDict, total=False): + description: str + quantity: Decimal + unit_cost: Decimal + is_active: bool + item_code: str | None + metal_type: str | None + alloy: str | None + specifics: str | None + + +def _stock(**overrides: Unpack[_StockOverrides]) -> Stock: + defaults: _StockOverrides = { + "description": "Generic material", + "quantity": Decimal("1.00"), + "unit_cost": Decimal("10.00"), + "is_active": True, + } defaults.update(overrides) return Stock.objects.create(**defaults) diff --git a/apps/workflow/tests/test_data_versions_view.py b/apps/workflow/tests/test_data_versions_view.py index 8572d460a..fadcbfa1d 100644 --- a/apps/workflow/tests/test_data_versions_view.py +++ b/apps/workflow/tests/test_data_versions_view.py @@ -3,7 +3,9 @@ string so the frontend invalidates its cache and re-fetches. """ +from datetime import datetime from decimal import Decimal +from typing import TypedDict, Unpack import pytest from django.utils import timezone @@ -39,12 +41,18 @@ def auth_client(office_staff): return api -def _stock(**overrides): - defaults = dict( - description="Test material", - quantity=Decimal("1.00"), - unit_cost=Decimal("10.00"), - ) +class _StockOverrides(TypedDict, total=False): + description: str + quantity: Decimal + unit_cost: Decimal + + +def _stock(**overrides: Unpack[_StockOverrides]) -> Stock: + defaults: _StockOverrides = { + "description": "Test material", + "quantity": Decimal("1.00"), + "unit_cost": Decimal("10.00"), + } defaults.update(overrides) return Stock.objects.create(**defaults) @@ -63,21 +71,35 @@ def kanban_prerequisites(db): ) -def _client(**overrides): - defaults = dict(name="Kanban Company", xero_last_modified=timezone.now()) +class _ClientOverrides(TypedDict, total=False): + name: str + xero_last_modified: datetime + + +def _client(**overrides: Unpack[_ClientOverrides]) -> Company: + defaults: _ClientOverrides = { + "name": "Kanban Company", + "xero_last_modified": timezone.now(), + } defaults.update(overrides) return Company.objects.create(**defaults) -def _job(staff, **overrides): - defaults = dict( - staff=staff, - company=_client(), - name="Kanban Job", - pricing_methodology="time_materials", - ) +class _JobOverrides(TypedDict, total=False): + company: Company + person: Person + name: str + pricing_methodology: str + + +def _job(staff: Staff, **overrides: Unpack[_JobOverrides]) -> Job: + defaults: _JobOverrides = { + "company": _client(), + "name": "Kanban Job", + "pricing_methodology": "time_materials", + } defaults.update(overrides) - return Job.objects.create(**defaults) + return Job.objects.create(staff=staff, **defaults) def _phone_call() -> PhoneCallRecord: diff --git a/apps/workflow/tests/test_localdate_regression.py b/apps/workflow/tests/test_localdate_regression.py index 7423e1a4e..2353e0b42 100644 --- a/apps/workflow/tests/test_localdate_regression.py +++ b/apps/workflow/tests/test_localdate_regression.py @@ -10,14 +10,21 @@ import datetime from decimal import Decimal +from typing import TYPE_CHECKING from unittest.mock import patch from django.test import TestCase from django.utils import timezone from freezegun import freeze_time +from apps.accounts.models import Staff +from apps.company.models import Company +from apps.job.models import Job from apps.testing import BaseTestCase +if TYPE_CHECKING: + from apps.workflow.views.xero.xero_invoice_manager import XeroInvoiceManager + # NZ ended DST on the first Sunday of April 2026 (April 5), so April 28 # is NZST = UTC+12. 23:30 UTC on April 27 == 11:30 NZST on April 28. FROZEN_UTC_MOMENT = "2026-04-27T23:30:00Z" @@ -26,15 +33,13 @@ DOCUMENT_THEME_ID = "00000000-0000-0000-0000-000000000286" -def _make_client(name="Localdate Test Company"): - from apps.company.models import Company - +def _make_client(name: str = "Localdate Test Company") -> Company: return Company.objects.create(name=name, xero_last_modified=timezone.now()) -def _make_job(company, staff, name="Localdate Test Job", **extra): - from apps.job.models import Job - +def _make_job( + company: Company, staff: Staff, name: str = "Localdate Test Job", **extra: object +) -> Job: job = Job(company=company, name=name, **extra) job.save(staff=staff) return job @@ -144,9 +149,7 @@ def test_currently_active_queryset_excludes_staff_who_left_today(self) -> None: class JobAgingLocalDateTests(BaseTestCase): """Aging calculations subtract dates; both halves must use the same tz.""" - def _make_aged_job(self): - from apps.job.models import Job - + def _make_aged_job(self) -> Job: company = _make_client("Aging Test Company") job = _make_job(company, self.test_staff, name="Aging Test Job") # Frozen "now" = UTC 2026-04-27 23:30 = NZ 2026-04-28 11:30 (UTC date @@ -220,7 +223,7 @@ class XeroInvoiceLocalDateTests(BaseTestCase): """The invoice payload sent to Xero and the local Invoice record both must be stamped with the NZ calendar date.""" - def _make_manager(self, *, is_account_customer): + def _make_manager(self, *, is_account_customer: bool) -> "XeroInvoiceManager": from apps.workflow.views.xero.xero_invoice_manager import XeroInvoiceManager company = _make_client("Xero Invoice Test Company") diff --git a/apps/workflow/tests/test_push_contacts.py b/apps/workflow/tests/test_push_contacts.py index 8d3a54237..74f54c4fa 100644 --- a/apps/workflow/tests/test_push_contacts.py +++ b/apps/workflow/tests/test_push_contacts.py @@ -18,7 +18,9 @@ from apps.workflow.tests.fixtures.xero_responses import make_create_contacts_response -def _make_client(**overrides): +def _make_client(**overrides: object) -> Company: + # `object` (not a TypedDict) because callers pass a non-field `phone` key + # that is popped and routed to a ContactMethod rather than Company.create(). defaults = { "name": "Acme Ltd", "email": "info@acme.test", @@ -38,7 +40,7 @@ def _make_client(**overrides): return company -def _create_response(contact_id, name): +def _create_response(contact_id: str, name: str) -> Contacts: """Mirror what AccountingApi.create_contacts / update_contact returns: a Contacts wrapper holding a list of Contact SDK instances.""" return Contacts(contacts=[Contact(contact_id=contact_id, name=name)]) diff --git a/apps/workflow/tests/test_session_replay_api.py b/apps/workflow/tests/test_session_replay_api.py index 1b0d9fb0f..1f598cd9a 100644 --- a/apps/workflow/tests/test_session_replay_api.py +++ b/apps/workflow/tests/test_session_replay_api.py @@ -40,7 +40,7 @@ def workshop_staff(db): ) -def _client(user): +def _client(user: Staff) -> APIClient: api = APIClient() api.force_authenticate(user=user) return api diff --git a/apps/workflow/tests/test_xero_app_api.py b/apps/workflow/tests/test_xero_app_api.py index 089654762..b52c1a713 100644 --- a/apps/workflow/tests/test_xero_app_api.py +++ b/apps/workflow/tests/test_xero_app_api.py @@ -3,6 +3,7 @@ import uuid from datetime import datetime, timedelta from datetime import timezone as dt_timezone +from typing import TypedDict, Unpack from unittest.mock import patch from rest_framework import status @@ -12,8 +13,22 @@ from apps.workflow.models import XeroApp -def _row(**overrides): - defaults = { +class _XeroAppOverrides(TypedDict, total=False): + label: str + client_id: str + client_secret: str + redirect_uri: str + is_active: bool + access_token: str | None + refresh_token: str | None + expires_at: datetime | None + day_remaining: int | None + minute_remaining: int | None + snapshot_at: datetime | None + + +def _row(**overrides: Unpack[_XeroAppOverrides]) -> XeroApp: + defaults: _XeroAppOverrides = { "label": "Primary", "client_id": "c-a", "client_secret": "s", @@ -24,7 +39,7 @@ def _row(**overrides): return XeroApp.objects.create(**defaults) -def _office_staff(email="office@example.test"): +def _office_staff(email: str = "office@example.test") -> Staff: return Staff.objects.create_user( email=email, password="x", diff --git a/apps/workflow/tests/test_xero_app_model.py b/apps/workflow/tests/test_xero_app_model.py index c3dba4913..3964d8c68 100644 --- a/apps/workflow/tests/test_xero_app_model.py +++ b/apps/workflow/tests/test_xero_app_model.py @@ -5,15 +5,25 @@ marked is_active=True at a time. """ +from typing import TypedDict, Unpack + from django.db import IntegrityError, transaction from django.test import TestCase from apps.workflow.models import XeroApp +class _XeroAppOverrides(TypedDict, total=False): + label: str + client_id: str + client_secret: str + redirect_uri: str + is_active: bool + + class XeroAppModelTests(TestCase): - def _row(self, **overrides): - defaults = { + def _row(self, **overrides: Unpack[_XeroAppOverrides]) -> XeroApp: + defaults: _XeroAppOverrides = { "label": "Primary", "client_id": "abc123", "client_secret": "shh", diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 924706083..b8b933130 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -30,6 +30,14 @@ apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generi apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/company/utils.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/services/geocoding_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] @@ -192,13 +200,11 @@ apps/job/services/workshop_pdf_service.py:0: error: Need type annotation for "st apps/job/services/workshop_pdf_service.py:0: error: Incompatible types in assignment (expression has type "list[Table | Flowable]", variable has type "list[Table]") [assignment] apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "wait_until_file_ready" in typed context [no-untyped-call] -apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_letterhead_banner" in typed context [no-untyped-call] apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_handover_section" in typed context [no-untyped-call] apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_letterhead_banner" in typed context [no-untyped-call] apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_handover_section" in typed context [no-untyped-call] apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] apps/job/services/workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/services/workshop_pdf_service.py:0: error: Argument 1 to "Table" has incompatible type "list[object]"; expected "Sequence[list[Any] | tuple[Any, ...]]" [arg-type] @@ -209,6 +215,61 @@ apps/purchasing/models.py:0: error: Call to untyped function "generate_po_number apps/purchasing/models.py:0: error: "PurchaseOrderLine" has no attribute "received_lines" [attr-defined] apps/purchasing/models.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/purchasing/models.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] +apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] +apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] +apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Call to untyped function "get_available_scrapers" in typed context [no-untyped-call] +apps/quoting/management/commands/run_scrapers.py:0: error: Argument 5 to "run_scraper" of "Command" has incompatible type "Any | None"; expected "bool" [arg-type] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] +apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] +apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int +apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T +apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] +apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_postrun" [attr-defined] docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_prerun" [attr-defined] docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_setup" untyped [untyped-decorator] @@ -217,8 +278,19 @@ apps/workflow/services/session_replay_service.py:0: error: Argument 1 to "Path" apps/workflow/services/session_replay_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/services/search_telemetry.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/services/search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/client.py:0: error: Class cannot subclass "RESTClientObject" (has type "Any") [misc] apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -257,7 +329,42 @@ apps/workflow/accounting/provider.py:0: error: Missing type arguments for generi apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/timesheet/services/xero_hours.py:0: error: Incompatible return value type (got "dict[str | None, Staff]", expected "dict[str, Staff]") [return-value] -apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: note: Use "-> None" if function does not return a value +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "CostLine") [assignment] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "Decimal") [assignment] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Argument 4 to "_split_costline" of "Command" has incompatible type "Decimal | CostLine | str | Any"; expected "str" [arg-type] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "date | Decimal | CostSet | Staff | str | Any", variable has type "Staff") [assignment] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "cost_set" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "CostSet | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "quantity" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "accounting_date" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | date | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "str" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] @@ -284,19 +391,12 @@ apps/purchasing/services/allocation_service.py:0: error: Incompatible return val apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] +apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] -apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "xero_id" [union-attr] apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr] apps/job/services/time_entry_rates.py:0: error: Incompatible return value type (got "Any | None", expected "XeroPayItem") [return-value] @@ -355,6 +455,18 @@ apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "find apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/importers/google_sheets.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Argument 3 to "_upload_to_google_docs" of "Command" has incompatible type "str | None"; expected "str" [arg-type] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Incompatible types in assignment (expression has type "Procedure", variable has type "Form") [assignment] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Need type annotation for "candidates" (hint: "candidates: dict[, ] = ...") [var-annotated] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "_get_drive_service" in typed context [no-untyped-call] apps/crm/services/phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] apps/crm/services/phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounting/services/sales_pipeline_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] @@ -370,104 +482,62 @@ apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid ind apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] apps/accounting/services/invoice_calculation.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] +apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] +apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] +apps/workflow/services/llm_service.py:0: note: Possible overload variants: +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str +apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/services/dev_demo_export_scrubber.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_xero_app_model.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_model.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "_make_company" in typed context [no-untyped-call] -apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Call to untyped function "get_available_scrapers" in typed context [no-untyped-call] -apps/quoting/management/commands/run_scrapers.py:0: error: Argument 5 to "run_scraper" of "Command" has incompatible type "Any | None"; expected "bool" [arg-type] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "CostLine") [assignment] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "Decimal") [assignment] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Argument 4 to "_split_costline" of "Command" has incompatible type "Decimal | CostLine | str | Any"; expected "str" [arg-type] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "date | Decimal | CostSet | Staff | str | Any", variable has type "Staff") [assignment] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "cost_set" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "CostSet | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "quantity" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "accounting_date" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | date | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "str" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/company/tests/test_get_company_for_xero.py:0: error: Incompatible type for "value" of "ContactMethod" (got "object", expected "str | int | Combinable") [misc] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -508,17 +578,23 @@ apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase apps/quoting/mcp.py:0: error: Need type annotation for "supplier_prices" (hint: "supplier_prices: dict[, ] = ...") [var-annotated] -apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] -apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/services/form_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/form_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] -apps/operations/services/scheduler_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] +apps/operations/services/scheduler_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] @@ -583,349 +659,142 @@ apps/process/services/google_docs_service.py:0: error: Missing type arguments fo apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Argument 3 to "_upload_to_google_docs" of "Command" has incompatible type "str | None"; expected "str" [arg-type] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Incompatible types in assignment (expression has type "Procedure", variable has type "Form") [assignment] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Need type annotation for "candidates" (hint: "candidates: dict[, ] = ...") [var-annotated] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "_get_drive_service" in typed context [no-untyped-call] apps/workflow/services/db_scrubber.py:0: error: Argument 1 to "add" of "set" has incompatible type "str | None"; expected "str" [arg-type] apps/job/services/data_integrity_service.py:0: error: Dict entry 4 has incompatible type "str": "list[str]"; expected "str": "str" [dict-item] apps/job/services/data_integrity_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] -apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] -apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] -apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_determine_status" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_get_staff_alerts" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Decimal") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Argument 2 to "_get_color" of "KPIService" has incompatible type "Decimal"; expected "float" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Argument "key" to "max" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/accounting/services/core.py:0: error: Argument 1 to "localtime" has incompatible type "object"; expected "datetime | None" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "date") [assignment] -apps/accounting/services/core.py:0: error: Incompatible return value type (got "None", expected "dict[str, Any]") [return-value] -apps/accounting/services/core.py:0: error: Generator has incompatible item type "Decimal"; expected "bool" [misc] -apps/accounting/services/core.py:0: error: "CostLine" has no attribute "is_billable_meta" [attr-defined] -apps/accounting/services/core.py:0: error: Argument 1 to "_calculate_job_breakdown" of "StaffPerformanceService" has incompatible type "list[CostLine]"; expected "QuerySet[Any, Any]" [arg-type] -apps/accounting/services/core.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "float") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for / ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for / ("str" and "float") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for / ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/workflow/serializers.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] -apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Field" defined the type as "dict[str, str | _StrPromise]") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "BooleanField", base class "Field" defined the type as "bool") [assignment] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "BooleanField", base class "Field" defined the type as "bool") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "SettingsFieldSerializer", base class "Serializer" defined the type as "BindingDict") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_office_staff" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_app_api.py:0: error: Call to untyped function "_row" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_search_telemetry.py:0: error: Call to untyped function "result_ids" in typed context [no-untyped-call] apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_job" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_job" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_job" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_job" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_client" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "_job" in typed context [no-untyped-call] apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -991,55 +860,17 @@ apps/process/tests/test_form_api.py:0: error: Function is missing a type annotat apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "JobQuoteChatSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_profitability_report_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1047,106 +878,12 @@ apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing t apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/accounting/serializers/rdti_spend_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] -apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] -apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance -apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] -apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/views/data_versions_view.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/views/build_id_view.py:0: error: Missing type arguments for generic type "list" [type-arg] apps/workflow/api/reports/pnl.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1200,29 +937,6 @@ apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "se apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Incompatible types in assignment (expression has type "SerializerMethodField", base class "CostSetSerializer" defined the type as "CostLineSerializer") [assignment] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "start_date" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Argument 1 to "_get_total_invoiced_for_job" of "SalesForecastMonthDetailAPIView" has incompatible type "Job | None"; expected "Job" [arg-type] apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "latest_actual" [union-attr] @@ -1232,6 +946,98 @@ apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | Non apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Argument "row_date" to "build_row" has incompatible type "Any | None"; expected "str" [arg-type] +apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] +apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] +apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] +apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] +apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance +apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] +apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value +apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value +apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] +apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] +apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] +apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] +apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "tuple[str, str, int] | None" is not indexable [index] apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "tuple[str, str, int] | None" is not indexable [index] apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] @@ -1273,29 +1079,9 @@ apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" apps/timesheet/tests/test_jobs_api_filter.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_make_special_leave_job" in typed context [no-untyped-call] apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_book_time" in typed context [no-untyped-call] @@ -1321,61 +1107,8 @@ apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "Alloca apps/operations/tests/test_scheduler_persistence.py:0: error: Item "None" of "SchedulerRun | None" has no attribute "id" [union-attr] apps/job/tests/test_workshop_timesheet_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/tests/test_workshop_timesheet_api.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Call to untyped function "convert_html_to_reportlab" in typed context [no-untyped-call] -apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_mcp_tool_integration.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] apps/job/tests/test_mcp_tool_integration.py:0: error: Missing positional argument "query" in call to "search_products" of "QuotingTool" [call-arg] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/job/tests/test_job_invoicing.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] apps/job/tests/test_job_files_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] apps/job/tests/test_costline_schema_validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] @@ -1406,970 +1139,468 @@ apps/accounting/tests/test_sales_pipeline_api.py:0: error: "type[SalesPipelineAP apps/accounting/tests/test_sales_pipeline_api.py:0: error: "SalesPipelineAPITests" has no attribute "office_staff" [attr-defined] apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounting/tests/test_sales_pipeline_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_invoice" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_invoice_calculation.py:0: error: Call to untyped function "_add_revenue_line" in typed context [no-untyped-call] -apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] -apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_files_collection_view.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Call to untyped function "save_file" in typed context [no-untyped-call] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_thumbnail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_create_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] -apps/job/tests/test_kanban_service.py:0: error: Call to untyped function "_set_summary_revenue" in typed context [no-untyped-call] apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_kanban_search.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_ordered_names" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_ordered_names" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_ordered_names" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_ordered_names" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] +apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Field" defined the type as "dict[str, str | _StrPromise]") [assignment] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "BooleanField", base class "Field" defined the type as "bool") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "BooleanField", base class "Field" defined the type as "bool") [assignment] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "SettingsFieldSerializer", base class "Serializer" defined the type as "BindingDict") [assignment] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "JobQuoteChatSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Incompatible types in assignment (expression has type "SerializerMethodField", base class "CostSetSerializer" defined the type as "CostLineSerializer") [assignment] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/mixins.py:0: error: Call to untyped function "get_job_by_number" in typed context [no-untyped-call] apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/mixins.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobSummaryDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "bool | None" [no-any-return] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Argument "choices" to "ChoiceField" has incompatible type "Sequence[tuple[Any, Any]] | Sequence[tuple[str, Iterable[tuple[Any, Any]]]] | None"; expected "Sequence[Any]" [arg-type] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "BindingDict") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Staff | AnonymousUser") [assignment] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] -apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] -apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/job/views/workshop_pdf_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "id" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "meta" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "quantity" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "unit_cost" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "calculated_total_cost" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostSet | None" has no attribute "rev" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/delivery_docket_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] -apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] -apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Call to untyped function "_stock" in typed context [no-untyped-call] -apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] -apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/kanban_view_api.py:0: error: "str" has no attribute "HTTP_500_INTERNAL_SERVER_ERROR" [attr-defined] -apps/job/views/kanban_view_api.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: "JobQuoteChatSerializer" has no attribute "get" [attr-defined] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Call to untyped function "_archive_quote_data" in typed context [no-untyped-call] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] -apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_staff_from_job" of "JobStaffService" in typed context [no-untyped-call] -apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] -apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] -apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] -apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] -apps/job/services/job_rest_service.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/services/job_rest_service.py:0: error: Argument "key" to "sort" of "list" has incompatible type "Callable[[dict[str, int | datetime | UUID | str | Any | None]], int | datetime | UUID | str | Any | None]"; expected "Callable[[dict[str, int | datetime | UUID | str | Any | None]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "int | datetime | UUID | str | Any | None", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/job/services/job_rest_service.py:0: error: Incompatible default for parameter "week" (default has type "None", parameter has type "date") [assignment] -apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Argument 1 to "get_weekly_metrics" of "JobRestService" has incompatible type "date | None"; expected "date" [arg-type] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: "type[Job]" has no attribute "STATUS_CHOICES" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_event" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] -apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] -apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] -apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] -apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] -apps/workflow/services/llm_service.py:0: note: Possible overload variants: -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str -apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value -apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] -apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] +apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] +apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_determine_status" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_get_staff_alerts" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] +apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Decimal") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Argument 2 to "_get_color" of "KPIService" has incompatible type "Decimal"; expected "float" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Argument "key" to "max" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/accounting/services/core.py:0: error: Argument 1 to "localtime" has incompatible type "object"; expected "datetime | None" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "date") [assignment] +apps/accounting/services/core.py:0: error: Incompatible return value type (got "None", expected "dict[str, Any]") [return-value] +apps/accounting/services/core.py:0: error: Generator has incompatible item type "Decimal"; expected "bool" [misc] +apps/accounting/services/core.py:0: error: "CostLine" has no attribute "is_billable_meta" [attr-defined] +apps/accounting/services/core.py:0: error: Argument 1 to "_calculate_job_breakdown" of "StaffPerformanceService" has incompatible type "list[CostLine]"; expected "QuerySet[Any, Any]" [arg-type] +apps/accounting/services/core.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for / ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for / ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for / ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] +apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] apps/job/services/chat_service.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] apps/job/services/chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] apps/job/services/chat_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] apps/job/services/chat_service.py:0: error: Cannot call function of unknown type [operator] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] +apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/job/tests/test_workshop_pdf_service.py:0: error: Argument 1 to "convert_html_to_reportlab" has incompatible type "None"; expected "str" [arg-type] +apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] @@ -2421,29 +1652,282 @@ apps/process/views/procedure_viewsets.py:0: error: Function is missing a type an apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] -apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_files_collection_view.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Call to untyped function "save_file" in typed context [no-untyped-call] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_thumbnail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobSummaryDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "bool | None" [no-any-return] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Argument "choices" to "ChoiceField" has incompatible type "Sequence[tuple[Any, Any]] | Sequence[tuple[str, Iterable[tuple[Any, Any]]]] | None"; expected "Sequence[Any]" [arg-type] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "BindingDict") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Staff | AnonymousUser") [assignment] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] apps/workflow/api/xero/auth.py:0: error: Call to untyped function "RateLimitedRESTClient" in typed context [no-untyped-call] apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] @@ -2616,41 +2100,6 @@ apps/workflow/api/xero/seed.py:0: error: Call to untyped function "_resolve_api_ apps/workflow/api/xero/seed.py:0: error: Dict entry 0 has incompatible type "str": "int"; expected "str": "str" [dict-item] apps/workflow/api/xero/seed.py:0: error: Argument 1 to "update" of "MutableMapping" has incompatible type "dict[str, str] | dict[str, bool]"; expected "SupportsKeysAndGetItem[str, str]" [arg-type] apps/workflow/api/xero/seed.py:0: error: Incompatible types in assignment (expression has type "int", target has type "str") [assignment] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] -apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] apps/workflow/views/xero_apps_view.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2694,45 +2143,186 @@ apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "syn apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] +apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Call to untyped function "build_timesheet_response" in typed context [no-untyped-call] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] +apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_pdf_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "id" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "meta" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "quantity" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "unit_cost" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "calculated_total_cost" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostSet | None" has no attribute "rev" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] +apps/job/views/delivery_docket_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] +apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] +apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] +apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] +apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] +apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] +apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Incompatible type for "value" of "ContactMethod" (got "object", expected "str | int | Combinable") [misc] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_create_response" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] apps/workflow/services/xero_sync_service.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] @@ -2753,152 +2343,49 @@ apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_t apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] -apps/timesheet/views/api.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Call to untyped function "build_timesheet_response" in typed context [no-untyped-call] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Need type annotation for "updated_line_ids" (hint: "updated_line_ids: set[] = ...") [var-annotated] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] -apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] -apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] -apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int -apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T -apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] -apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_contact" in typed context [no-untyped-call] -apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_invoice" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Argument 1 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument 3 to "exchange_code_for_token" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Returning Any from function declared to return "HttpResponse" [no-any-return] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible return value type (got "JsonResponse", expected "StreamingHttpResponse") [return-value] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "generate_xero_sync_events" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentSuccessResponseSerializer", variable has type "XeroDocumentErrorResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "xero_invoice_id" to "XeroInvoiceManager" has incompatible type "UUID"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] -apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_aged_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_manager" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_client" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "_make_job" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Need type annotation for "updated_line_ids" (hint: "updated_line_ids: set[] = ...") [var-annotated] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] +apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2942,14 +2429,81 @@ apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a t apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] -apps/workflow/xero_webhooks.py:0: error: "Callable[[str, dict[str, Any]], None]" has no attribute "delay" [attr-defined] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] +apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/kanban_view_api.py:0: error: "str" has no attribute "HTTP_500_INTERNAL_SERVER_ERROR" [attr-defined] +apps/job/views/kanban_view_api.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: "JobQuoteChatSerializer" has no attribute "get" [attr-defined] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Call to untyped function "_archive_quote_data" in typed context [no-untyped-call] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] +apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_staff_from_job" of "JobStaffService" in typed context [no-untyped-call] +apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] +apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] +apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] +apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] +apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] +apps/job/services/job_rest_service.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/services/job_rest_service.py:0: error: Argument "key" to "sort" of "list" has incompatible type "Callable[[dict[str, int | datetime | UUID | str | Any | None]], int | datetime | UUID | str | Any | None]"; expected "Callable[[dict[str, int | datetime | UUID | str | Any | None]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "int | datetime | UUID | str | Any | None", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/job/services/job_rest_service.py:0: error: Incompatible default for parameter "week" (default has type "None", parameter has type "date") [assignment] +apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_contact" in typed context [no-untyped-call] +apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_invoice" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] @@ -2987,6 +2541,7 @@ apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.api.xero.stock_sync" does not explicitly export attribute "XeroAccount" [attr-defined] apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_gen" in typed context [no-untyped-call] apps/workflow/tests/test_tasks.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] apps/workflow/tests/test_celery_setup.py:0: error: "Celery" has no attribute "main" [attr-defined] @@ -2997,6 +2552,50 @@ apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Argument 1 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 3 to "exchange_code_for_token" has incompatible type "Any | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Returning Any from function declared to return "HttpResponse" [no-any-return] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible return value type (got "JsonResponse", expected "StreamingHttpResponse") [return-value] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "generate_xero_sync_events" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentSuccessResponseSerializer", variable has type "XeroDocumentErrorResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "xero_invoice_id" to "XeroInvoiceManager" has incompatible type "UUID"; expected "str | None" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] apps/workflow/tests/test_xero_po_manager.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "supplier" [attr-defined] apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "purchase_order" [attr-defined] @@ -3004,6 +2603,13 @@ apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderMan apps/workflow/tests/test_xero_po_manager.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_po_manager.py:0: error: "XeroPurchaseOrderManagerConstructionTests" has no attribute "purchase_order" [attr-defined] apps/workflow/tests/test_xero_app_active.py:0: error: Value of type "dict[str, Any] | None" is not indexable [index] +apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] @@ -3052,10 +2658,52 @@ apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to u apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Incompatible types in assignment (expression has type "StringIO", variable has type "OutputWrapper") [assignment] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Argument 1 to "get_weekly_metrics" of "JobRestService" has incompatible type "date | None"; expected "date" [arg-type] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: "type[Job]" has no attribute "STATUS_CHOICES" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/xero_webhooks.py:0: error: "Callable[[str, dict[str, Any]], None]" has no attribute "delay" [attr-defined] apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -3098,8 +2746,6 @@ apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a retu apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -3118,6 +2764,44 @@ apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped functio apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_leave_names" in typed context [no-untyped-call] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Cannot assign to a method [method-assign] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] From 09ac18be30159457b03ae20dc9f5def8a3c9774f Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 11:52:47 +1200 Subject: [PATCH 23/39] chore: gitignore Qwen Code per-session state .qwen/settings.json holds developer-specific permission grants written by the Qwen Code CLI during a session; like .codex/ and .anthropic/ it is local tooling state, not project config. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c6e5710e7..0c817241e 100644 --- a/.gitignore +++ b/.gitignore @@ -269,6 +269,9 @@ session-replays/ .mcp.json .codex +# Qwen Code per-session state (developer-specific permission grants) +.qwen/ + # Codesight autogenerated context maps. Regenerated by the pre-commit # `post-merge` / `post-rewrite` hooks (`pre-commit install` wires them up # automatically — see `default_install_hook_types` in From c134c1c4fe30e60f0425db6afa855cea8c377113 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 13:04:01 +1200 Subject: [PATCH 24/39] KAN-316 test: annotate remaining test factory helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second pass over the hot test helpers: the XeroApp/quota, XeroPayItem, Company, Job, and service factories. Most take Unpack[TypedDict] keyed on the override fields callers actually pass — including the company builders that pop a non-field phone key before create(), which a TypedDict describes fine once phone is a declared key. _consume keeps Iterator[object] because sync_xero_data is untyped and yields unschema'd dict events; _job casts its create() result, which django-stubs types as Any under Unpack kwargs. --- .../tests/test_get_company_for_xero.py | 19 +- apps/process/tests/test_form_service.py | 2 +- apps/process/tests/test_procedure_service.py | 2 +- .../workflow/tests/test_data_versions_view.py | 5 +- .../tests/test_localdate_regression.py | 15 +- apps/workflow/tests/test_push_contacts.py | 17 +- apps/workflow/tests/test_xero_quota_floor.py | 37 +- .../workflow/tests/test_xero_setup_command.py | 15 +- mypy-baseline.txt | 2464 ++++++++--------- 9 files changed, 1291 insertions(+), 1285 deletions(-) diff --git a/apps/company/tests/test_get_company_for_xero.py b/apps/company/tests/test_get_company_for_xero.py index e06bf0a51..66fc72f93 100644 --- a/apps/company/tests/test_get_company_for_xero.py +++ b/apps/company/tests/test_get_company_for_xero.py @@ -7,6 +7,9 @@ attribute_map translates to PascalCase correctly. """ +from datetime import datetime +from typing import TypedDict, Unpack + from django.test import TestCase from django.utils import timezone from xero_python.accounting.models import Address, Contact, Phone @@ -15,13 +18,21 @@ from apps.company.models import Company, ContactMethod +class _CompanyOverrides(TypedDict, total=False): + name: str + email: str | None + address: str | None + xero_last_modified: datetime + xero_contact_id: str + is_account_customer: bool + phone: str | None + + class GetCompanyForXeroTests(TestCase): """Pin the wire-format contract independent of which push function consumes it.""" - def _make_company(self, **overrides: object) -> Company: - # `object` (not a TypedDict) because callers pass a non-field `phone` - # key that is popped and routed to a ContactMethod, not Company.create(). - defaults = { + def _make_company(self, **overrides: Unpack[_CompanyOverrides]) -> Company: + defaults: _CompanyOverrides = { "name": "Acme Ltd", "xero_last_modified": timezone.now(), } diff --git a/apps/process/tests/test_form_service.py b/apps/process/tests/test_form_service.py index 80fe53fe5..cb3827277 100644 --- a/apps/process/tests/test_form_service.py +++ b/apps/process/tests/test_form_service.py @@ -4,7 +4,7 @@ from apps.process.services.form_service import FormService -def _make_service(): +def _make_service() -> FormService: """Create a FormService.""" return FormService() diff --git a/apps/process/tests/test_procedure_service.py b/apps/process/tests/test_procedure_service.py index f326a58e2..aa3a894c7 100644 --- a/apps/process/tests/test_procedure_service.py +++ b/apps/process/tests/test_procedure_service.py @@ -9,7 +9,7 @@ from apps.workflow.models import CompanyDefaults -def _make_service(): +def _make_service() -> ProcedureService: """Create a ProcedureService with external dependencies mocked out.""" with ( patch("apps.process.services.procedure_service.SafetyAIService"), diff --git a/apps/workflow/tests/test_data_versions_view.py b/apps/workflow/tests/test_data_versions_view.py index fadcbfa1d..f55aae25e 100644 --- a/apps/workflow/tests/test_data_versions_view.py +++ b/apps/workflow/tests/test_data_versions_view.py @@ -5,7 +5,7 @@ from datetime import datetime from decimal import Decimal -from typing import TypedDict, Unpack +from typing import TypedDict, Unpack, cast import pytest from django.utils import timezone @@ -99,7 +99,8 @@ def _job(staff: Staff, **overrides: Unpack[_JobOverrides]) -> Job: "pricing_methodology": "time_materials", } defaults.update(overrides) - return Job.objects.create(staff=staff, **defaults) + # create() returns Any when fed Unpack kwargs; the row is always a Job. + return cast(Job, Job.objects.create(staff=staff, **defaults)) def _phone_call() -> PhoneCallRecord: diff --git a/apps/workflow/tests/test_localdate_regression.py b/apps/workflow/tests/test_localdate_regression.py index 2353e0b42..787e4ebf2 100644 --- a/apps/workflow/tests/test_localdate_regression.py +++ b/apps/workflow/tests/test_localdate_regression.py @@ -10,7 +10,7 @@ import datetime from decimal import Decimal -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, TypedDict, Unpack from unittest.mock import patch from django.test import TestCase @@ -37,8 +37,19 @@ def _make_client(name: str = "Localdate Test Company") -> Company: return Company.objects.create(name=name, xero_last_modified=timezone.now()) +class _JobExtras(TypedDict, total=False): + pricing_methodology: str + status: str + fully_invoiced: bool + paid: bool + rejected_flag: bool + + def _make_job( - company: Company, staff: Staff, name: str = "Localdate Test Job", **extra: object + company: Company, + staff: Staff, + name: str = "Localdate Test Job", + **extra: Unpack[_JobExtras], ) -> Job: job = Job(company=company, name=name, **extra) job.save(staff=staff) diff --git a/apps/workflow/tests/test_push_contacts.py b/apps/workflow/tests/test_push_contacts.py index 74f54c4fa..abffd38c0 100644 --- a/apps/workflow/tests/test_push_contacts.py +++ b/apps/workflow/tests/test_push_contacts.py @@ -8,6 +8,8 @@ There is no prior test coverage for these functions; this is the first. """ +from datetime import datetime +from typing import TypedDict, Unpack from unittest.mock import patch from django.test import TestCase @@ -18,10 +20,17 @@ from apps.workflow.tests.fixtures.xero_responses import make_create_contacts_response -def _make_client(**overrides: object) -> Company: - # `object` (not a TypedDict) because callers pass a non-field `phone` key - # that is popped and routed to a ContactMethod rather than Company.create(). - defaults = { +class _ClientOverrides(TypedDict, total=False): + name: str + email: str | None + address: str | None + xero_last_modified: datetime + xero_contact_id: str + phone: str | None + + +def _make_client(**overrides: Unpack[_ClientOverrides]) -> Company: + defaults: _ClientOverrides = { "name": "Acme Ltd", "email": "info@acme.test", "address": "123 Test Street", diff --git a/apps/workflow/tests/test_xero_quota_floor.py b/apps/workflow/tests/test_xero_quota_floor.py index f67ac9afc..84993f62f 100644 --- a/apps/workflow/tests/test_xero_quota_floor.py +++ b/apps/workflow/tests/test_xero_quota_floor.py @@ -12,10 +12,13 @@ (batches of 50) rather than per-item ``update_item`` calls. """ -from datetime import timedelta +from collections.abc import Iterator +from datetime import datetime, timedelta from decimal import Decimal from types import SimpleNamespace +from typing import TypedDict, Unpack from unittest.mock import MagicMock, patch +from uuid import UUID from django.core.cache import cache, caches from django.test import TestCase @@ -37,9 +40,20 @@ _shared = caches["shared"] -def _active_app(**overrides): +class _ActiveAppOverrides(TypedDict, total=False): + label: str + client_id: str + client_secret: str + redirect_uri: str + is_active: bool + day_remaining: int | None + minute_remaining: int | None + snapshot_at: datetime | None + + +def _active_app(**overrides: Unpack[_ActiveAppOverrides]) -> XeroApp: """Create an active XeroApp row with sensible defaults.""" - defaults = { + defaults: _ActiveAppOverrides = { "label": "Primary", "client_id": "test-c", "client_secret": "s", @@ -50,7 +64,9 @@ def _active_app(**overrides): return XeroApp.objects.create(**defaults) -def _set_quota(day_remaining, minute_remaining=60, snapshot_age_seconds=0): +def _set_quota( + day_remaining: int, minute_remaining: int = 60, snapshot_age_seconds: int = 0 +) -> None: """Set the active XeroApp's snapshot to specific values. Creates an active row if none exists, otherwise updates the existing one. @@ -70,7 +86,7 @@ def _set_quota(day_remaining, minute_remaining=60, snapshot_age_seconds=0): ) -def _set_company_floor(floor=100): +def _set_company_floor(floor: int = 100) -> None: CompanyDefaults.clear_cache() updated = CompanyDefaults.objects.filter(pk=1).update( xero_automated_day_floor=floor @@ -141,8 +157,13 @@ class RateLimit429WritesToActiveRowTests(TestCase): moment of write.""" def _run_handle_rate_limit( - self, *, app_id, day_remaining, minute_remaining, problem - ): + self, + *, + app_id: UUID, + day_remaining: int, + minute_remaining: int, + problem: str, + ) -> None: from apps.workflow.api.xero.client import RateLimitedRESTClient # Build a minimal fake exception that matches what the SDK passes in. @@ -361,7 +382,7 @@ def setUp(self) -> None: # TestCase's per-test transaction rollback. _set_company_floor() - def _consume(self, generator): + def _consume(self, generator: Iterator[object]) -> list[object]: """Fully iterate the generator and return its emitted events.""" return list(generator) diff --git a/apps/workflow/tests/test_xero_setup_command.py b/apps/workflow/tests/test_xero_setup_command.py index e30bd6f69..2dc131bff 100644 --- a/apps/workflow/tests/test_xero_setup_command.py +++ b/apps/workflow/tests/test_xero_setup_command.py @@ -2,6 +2,7 @@ from decimal import Decimal from pathlib import Path from types import SimpleNamespace +from typing import TypedDict, Unpack from unittest.mock import Mock, patch from uuid import UUID @@ -13,22 +14,28 @@ from apps.workflow.models import XeroPayItem +class _PayItemOverrides(TypedDict, total=False): + name: str + multiplier: Decimal | None + xero_id: str | None + + class EnsureDemoXeroItemsExistTests(TestCase): - def _earnings_names(self): + def _earnings_names(self) -> list[str]: return list( XeroPayItem.objects.filter(uses_leave_api=False) .order_by("name") .values_list("name", flat=True) ) - def _leave_names(self): + def _leave_names(self) -> list[str]: return list( XeroPayItem.objects.filter(uses_leave_api=True) .order_by("name") .values_list("name", flat=True) ) - def _earnings_item(self, **overrides): + def _earnings_item(self, **overrides: Unpack[_PayItemOverrides]) -> XeroPayItem: name = overrides.pop("name", "Time and one half") item = XeroPayItem.objects.get(name=name, uses_leave_api=False) item.multiplier = overrides.pop("multiplier", Decimal("1.50")) @@ -38,7 +45,7 @@ def _earnings_item(self, **overrides): item.save() return item - def _leave_item(self, **overrides): + def _leave_item(self, **overrides: Unpack[_PayItemOverrides]) -> XeroPayItem: name = overrides.pop("name", "Annual Leave") item = XeroPayItem.objects.get(name=name, uses_leave_api=True) item.multiplier = overrides.pop("multiplier", None) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index b8b933130..229de4c2d 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -30,14 +30,6 @@ apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generi apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/company/utils.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/services/geocoding_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] @@ -215,61 +207,6 @@ apps/purchasing/models.py:0: error: Call to untyped function "generate_po_number apps/purchasing/models.py:0: error: "PurchaseOrderLine" has no attribute "received_lines" [attr-defined] apps/purchasing/models.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/purchasing/models.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] -apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] -apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] -apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Call to untyped function "get_available_scrapers" in typed context [no-untyped-call] -apps/quoting/management/commands/run_scrapers.py:0: error: Argument 5 to "run_scraper" of "Command" has incompatible type "Any | None"; expected "bool" [arg-type] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] -apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] -apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int -apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T -apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] -apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_postrun" [attr-defined] docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_prerun" [attr-defined] docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_setup" untyped [untyped-decorator] @@ -278,19 +215,8 @@ apps/workflow/services/session_replay_service.py:0: error: Argument 1 to "Path" apps/workflow/services/session_replay_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/services/search_telemetry.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/services/search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] apps/workflow/api/xero/client.py:0: error: Class cannot subclass "RESTClientObject" (has type "Any") [misc] apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -329,42 +255,7 @@ apps/workflow/accounting/provider.py:0: error: Missing type arguments for generi apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/timesheet/services/xero_hours.py:0: error: Incompatible return value type (got "dict[str | None, Staff]", expected "dict[str, Staff]") [return-value] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "CostLine") [assignment] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "Decimal") [assignment] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Argument 4 to "_split_costline" of "Command" has incompatible type "Decimal | CostLine | str | Any"; expected "str" [arg-type] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "date | Decimal | CostSet | Staff | str | Any", variable has type "Staff") [assignment] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "cost_set" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "CostSet | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "quantity" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "accounting_date" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | date | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "str" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] @@ -391,12 +282,19 @@ apps/purchasing/services/allocation_service.py:0: error: Incompatible return val apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] -apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] +apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "xero_id" [union-attr] apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr] apps/job/services/time_entry_rates.py:0: error: Incompatible return value type (got "Any | None", expected "XeroPayItem") [return-value] @@ -455,18 +353,6 @@ apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "find apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/importers/google_sheets.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Argument 3 to "_upload_to_google_docs" of "Command" has incompatible type "str | None"; expected "str" [arg-type] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Incompatible types in assignment (expression has type "Procedure", variable has type "Form") [assignment] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Need type annotation for "candidates" (hint: "candidates: dict[, ] = ...") [var-annotated] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "_get_drive_service" in typed context [no-untyped-call] apps/crm/services/phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] apps/crm/services/phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounting/services/sales_pipeline_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] @@ -482,51 +368,16 @@ apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid ind apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] apps/accounting/services/invoice_calculation.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] -apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] -apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] -apps/workflow/services/llm_service.py:0: note: Possible overload variants: -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str -apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/services/dev_demo_export_scrubber.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: error: Incompatible type for "value" of "ContactMethod" (got "object", expected "str | int | Combinable") [misc] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] @@ -537,7 +388,73 @@ apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped functi apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Call to untyped function "get_available_scrapers" in typed context [no-untyped-call] +apps/quoting/management/commands/run_scrapers.py:0: error: Argument 5 to "run_scraper" of "Command" has incompatible type "Any | None"; expected "bool" [arg-type] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: note: Use "-> None" if function does not return a value +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "CostLine") [assignment] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "Decimal") [assignment] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Argument 4 to "_split_costline" of "Command" has incompatible type "Decimal | CostLine | str | Any"; expected "str" [arg-type] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "date | Decimal | CostSet | Staff | str | Any", variable has type "Staff") [assignment] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "cost_set" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "CostSet | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "quantity" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "accounting_date" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | date | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "str" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -578,16 +495,10 @@ apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase apps/quoting/mcp.py:0: error: Need type annotation for "supplier_prices" (hint: "supplier_prices: dict[, ] = ...") [var-annotated] +apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] +apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/services/form_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/form_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/process/tests/test_form_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_form_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] apps/operations/services/scheduler_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] @@ -659,138 +570,236 @@ apps/process/services/google_docs_service.py:0: error: Missing type arguments fo apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/db_scrubber.py:0: error: Argument 1 to "add" of "set" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/services/data_integrity_service.py:0: error: Dict entry 4 has incompatible type "str": "list[str]"; expected "str": "str" [dict-item] -apps/job/services/data_integrity_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Argument 3 to "_upload_to_google_docs" of "Command" has incompatible type "str | None"; expected "str" [arg-type] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Incompatible types in assignment (expression has type "Procedure", variable has type "Form") [assignment] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Need type annotation for "candidates" (hint: "candidates: dict[, ] = ...") [var-annotated] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "_get_drive_service" in typed context [no-untyped-call] +apps/workflow/services/db_scrubber.py:0: error: Argument 1 to "add" of "set" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/services/data_integrity_service.py:0: error: Dict entry 4 has incompatible type "str": "list[str]"; expected "str": "str" [dict-item] +apps/job/services/data_integrity_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] +apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] +apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] +apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] +apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_determine_status" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_get_staff_alerts" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Decimal") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Argument 2 to "_get_color" of "KPIService" has incompatible type "Decimal"; expected "float" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Argument "key" to "max" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/accounting/services/core.py:0: error: Argument 1 to "localtime" has incompatible type "object"; expected "datetime | None" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "date") [assignment] +apps/accounting/services/core.py:0: error: Incompatible return value type (got "None", expected "dict[str, Any]") [return-value] +apps/accounting/services/core.py:0: error: Generator has incompatible item type "Decimal"; expected "bool" [misc] +apps/accounting/services/core.py:0: error: "CostLine" has no attribute "is_billable_meta" [attr-defined] +apps/accounting/services/core.py:0: error: Argument 1 to "_calculate_job_breakdown" of "StaffPerformanceService" has incompatible type "list[CostLine]"; expected "QuerySet[Any, Any]" [arg-type] +apps/accounting/services/core.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for / ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for / ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for / ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/tests/test_search_telemetry.py:0: error: Call to untyped function "result_ids" in typed context [no-untyped-call] @@ -866,6 +875,8 @@ apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing ty apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -878,12 +889,84 @@ apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing t apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/accounting/serializers/rdti_spend_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] +apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] +apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance +apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] +apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/views/data_versions_view.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/views/build_id_view.py:0: error: Missing type arguments for generic type "list" [type-arg] apps/workflow/api/reports/pnl.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -946,98 +1029,6 @@ apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | Non apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Argument "row_date" to "build_row" has incompatible type "Any | None"; expected "str" [arg-type] -apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] -apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] -apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] -apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] -apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance -apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] -apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value -apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value -apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] -apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] -apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] -apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] -apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "_make_service" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "tuple[str, str, int] | None" is not indexable [index] apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "tuple[str, str, int] | None" is not indexable [index] apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] @@ -1079,6 +1070,26 @@ apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" apps/timesheet/tests/test_jobs_api_filter.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/timesheet/tests/test_jobs_api_filter.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1107,6 +1118,8 @@ apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "Alloca apps/operations/tests/test_scheduler_persistence.py:0: error: Item "None" of "SchedulerRun | None" has no attribute "id" [union-attr] apps/job/tests/test_workshop_timesheet_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/job/tests/test_workshop_timesheet_api.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/job/tests/test_workshop_pdf_service.py:0: error: Argument 1 to "convert_html_to_reportlab" has incompatible type "None"; expected "str" [arg-type] +apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_mcp_tool_integration.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] apps/job/tests/test_mcp_tool_integration.py:0: error: Missing positional argument "query" in call to "search_products" of "QuotingTool" [call-arg] apps/job/tests/test_job_files_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] @@ -1124,78 +1137,24 @@ apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezon apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/tests/test_company_merge_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/company/tests/test_company_merge_service.py:0: error: Value of type "Any | None" is not indexable [index] -apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: "type[SalesPipelineAPITests]" has no attribute "office_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: "SalesPipelineAPITests" has no attribute "office_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] -apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/company/tests/test_company_merge_service.py:0: error: Value of type "Any | None" is not indexable [index] +apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: "type[SalesPipelineAPITests]" has no attribute "office_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: "SalesPipelineAPITests" has no attribute "office_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] +apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/serializers.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1235,34 +1194,6 @@ apps/workflow/serializers.py:0: error: Missing type arguments for generic type " apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1315,216 +1246,25 @@ apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Call to untyped function "get_job_by_number" in typed context [no-untyped-call] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] -apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] -apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_determine_status" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_get_staff_alerts" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] -apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Decimal") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Argument 2 to "_get_color" of "KPIService" has incompatible type "Decimal"; expected "float" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Argument "key" to "max" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/accounting/services/core.py:0: error: Argument 1 to "localtime" has incompatible type "object"; expected "datetime | None" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "date") [assignment] -apps/accounting/services/core.py:0: error: Incompatible return value type (got "None", expected "dict[str, Any]") [return-value] -apps/accounting/services/core.py:0: error: Generator has incompatible item type "Decimal"; expected "bool" [misc] -apps/accounting/services/core.py:0: error: "CostLine" has no attribute "is_billable_meta" [attr-defined] -apps/accounting/services/core.py:0: error: Argument 1 to "_calculate_job_breakdown" of "StaffPerformanceService" has incompatible type "list[CostLine]"; expected "QuerySet[Any, Any]" [arg-type] -apps/accounting/services/core.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "float") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for / ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for / ("str" and "float") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for / ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] -apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] +apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1537,55 +1277,40 @@ apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/job/services/chat_service.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] -apps/job/services/chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/chat_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/chat_service.py:0: error: Cannot call function of unknown type [operator] -apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] -apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/job/tests/test_workshop_pdf_service.py:0: error: Argument 1 to "convert_html_to_reportlab" has incompatible type "None"; expected "str" [arg-type] -apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_kanban_search.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] +apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Call to untyped function "get_job_by_number" in typed context [no-untyped-call] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/kanban_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1601,82 +1326,6 @@ apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for g apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Argument "document_type" to "create_blank_procedure" of "ProcedureService" has incompatible type "Sequence[str]"; expected "str" [arg-type] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "update" of "ProcedureViewSet" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] @@ -1867,24 +1516,140 @@ apps/purchasing/serializers.py:0: error: Missing type arguments for generic type apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_pdf_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "id" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "meta" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "quantity" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "unit_cost" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "calculated_total_cost" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostSet | None" has no attribute "rev" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/delivery_docket_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] +apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] +apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] +apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] +apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1916,18 +1681,461 @@ apps/company/tests/test_company_fts_search.py:0: error: Function is missing a ty apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_fts_search.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Staff | AnonymousUser") [assignment] apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] +apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] +apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/kanban_view_api.py:0: error: "str" has no attribute "HTTP_500_INTERNAL_SERVER_ERROR" [attr-defined] +apps/job/views/kanban_view_api.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: "JobQuoteChatSerializer" has no attribute "get" [attr-defined] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Call to untyped function "_archive_quote_data" in typed context [no-untyped-call] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] +apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_staff_from_job" of "JobStaffService" in typed context [no-untyped-call] +apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] +apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] +apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] +apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] +apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] +apps/job/services/job_rest_service.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/services/job_rest_service.py:0: error: Argument "key" to "sort" of "list" has incompatible type "Callable[[dict[str, int | datetime | UUID | str | Any | None]], int | datetime | UUID | str | Any | None]"; expected "Callable[[dict[str, int | datetime | UUID | str | Any | None]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "int | datetime | UUID | str | Any | None", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/job/services/job_rest_service.py:0: error: Incompatible default for parameter "week" (default has type "None", parameter has type "date") [assignment] +apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] +apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Argument 1 to "get_weekly_metrics" of "JobRestService" has incompatible type "date | None"; expected "date" [arg-type] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: "type[Job]" has no attribute "STATUS_CHOICES" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] +apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] +apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] +apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] +apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] +apps/workflow/services/llm_service.py:0: note: Possible overload variants: +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str +apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value +apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] +apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/job/services/chat_service.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] +apps/job/services/chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/chat_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/services/chat_service.py:0: error: Cannot call function of unknown type [operator] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Argument "document_type" to "create_blank_procedure" of "ProcedureService" has incompatible type "Sequence[str]"; expected "str" [arg-type] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "update" of "ProcedureViewSet" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "return_value" [attr-defined] +apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "assert_called_once_with" [attr-defined] +apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] +apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/auth.py:0: error: Call to untyped function "RateLimitedRESTClient" in typed context [no-untyped-call] apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] @@ -2100,6 +2308,41 @@ apps/workflow/api/xero/seed.py:0: error: Call to untyped function "_resolve_api_ apps/workflow/api/xero/seed.py:0: error: Dict entry 0 has incompatible type "str": "int"; expected "str": "str" [dict-item] apps/workflow/api/xero/seed.py:0: error: Argument 1 to "update" of "MutableMapping" has incompatible type "dict[str, str] | dict[str, bool]"; expected "SupportsKeysAndGetItem[str, str]" [arg-type] apps/workflow/api/xero/seed.py:0: error: Incompatible types in assignment (expression has type "int", target has type "str") [assignment] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] +apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] apps/workflow/views/xero_apps_view.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2143,164 +2386,6 @@ apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "syn apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] -apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Call to untyped function "build_timesheet_response" in typed context [no-untyped-call] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] -apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_pdf_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "id" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "meta" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "quantity" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "unit_cost" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "calculated_total_cost" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostSet | None" has no attribute "rev" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] -apps/job/views/delivery_docket_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] -apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] -apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] -apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] -apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] -apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Incompatible type for "value" of "ContactMethod" (got "object", expected "str | int | Combinable") [misc] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2323,6 +2408,8 @@ apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] @@ -2371,6 +2458,22 @@ apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for g apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/accounting/xero/provider.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/timesheet/views/api.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Call to untyped function "build_timesheet_response" in typed context [no-untyped-call] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] @@ -2386,6 +2489,71 @@ apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped fu apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] +apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] +apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int +apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T +apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] +apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_contact" in typed context [no-untyped-call] +apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_invoice" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Argument 1 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 3 to "exchange_code_for_token" has incompatible type "Any | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Returning Any from function declared to return "HttpResponse" [no-any-return] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible return value type (got "JsonResponse", expected "StreamingHttpResponse") [return-value] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "generate_xero_sync_events" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentSuccessResponseSerializer", variable has type "XeroDocumentErrorResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "xero_invoice_id" to "XeroInvoiceManager" has incompatible type "UUID"; expected "str | None" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] +apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2429,116 +2597,19 @@ apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a t apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] -apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/kanban_view_api.py:0: error: "str" has no attribute "HTTP_500_INTERNAL_SERVER_ERROR" [attr-defined] -apps/job/views/kanban_view_api.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: "JobQuoteChatSerializer" has no attribute "get" [attr-defined] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Call to untyped function "_archive_quote_data" in typed context [no-untyped-call] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] -apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_staff_from_job" of "JobStaffService" in typed context [no-untyped-call] -apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] -apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] -apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] -apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] -apps/job/services/job_rest_service.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/services/job_rest_service.py:0: error: Argument "key" to "sort" of "list" has incompatible type "Callable[[dict[str, int | datetime | UUID | str | Any | None]], int | datetime | UUID | str | Any | None]"; expected "Callable[[dict[str, int | datetime | UUID | str | Any | None]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "int | datetime | UUID | str | Any | None", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/job/services/job_rest_service.py:0: error: Incompatible default for parameter "week" (default has type "None", parameter has type "date") [assignment] -apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_contact" in typed context [no-untyped-call] -apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_invoice" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] +apps/workflow/xero_webhooks.py:0: error: "Callable[[str, dict[str, Any]], None]" has no attribute "delay" [attr-defined] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_run_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_run_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_run_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_company_floor" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_company_floor" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_consume" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_quota" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_consume" in typed context [no-untyped-call] apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_set_company_floor" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_active_app" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: "object" has no attribute "get" [attr-defined] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Unexpected keyword argument "access_token" for "_active_app" [call-arg] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Unexpected keyword argument "refresh_token" for "_active_app" [call-arg] apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.api.xero.stock_sync" does not explicitly export attribute "XeroAccount" [attr-defined] apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2552,50 +2623,6 @@ apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Argument 1 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument 3 to "exchange_code_for_token" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Returning Any from function declared to return "HttpResponse" [no-any-return] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible return value type (got "JsonResponse", expected "StreamingHttpResponse") [return-value] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "generate_xero_sync_events" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentSuccessResponseSerializer", variable has type "XeroDocumentErrorResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "xero_invoice_id" to "XeroInvoiceManager" has incompatible type "UUID"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] apps/workflow/tests/test_xero_po_manager.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "supplier" [attr-defined] apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "purchase_order" [attr-defined] @@ -2603,13 +2630,6 @@ apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderMan apps/workflow/tests/test_xero_po_manager.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_po_manager.py:0: error: "XeroPurchaseOrderManagerConstructionTests" has no attribute "purchase_order" [attr-defined] apps/workflow/tests/test_xero_app_active.py:0: error: Value of type "dict[str, Any] | None" is not indexable [index] -apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] -apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] @@ -2658,52 +2678,10 @@ apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to u apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Incompatible types in assignment (expression has type "StringIO", variable has type "OutputWrapper") [assignment] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Argument 1 to "get_weekly_metrics" of "JobRestService" has incompatible type "date | None"; expected "date" [arg-type] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: "type[Job]" has no attribute "STATUS_CHOICES" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/xero_webhooks.py:0: error: "Callable[[str, dict[str, Any]], None]" has no attribute "delay" [attr-defined] apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2746,62 +2724,13 @@ apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a retu apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_earnings_item" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_leave_item" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_earnings_names" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_leave_names" in typed context [no-untyped-call] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_leave_item" in typed context [no-untyped-call] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_earnings_item" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_leave_item" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_earnings_names" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_setup_command.py:0: error: Call to untyped function "_leave_names" in typed context [no-untyped-call] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Cannot assign to a method [method-assign] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] -apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] @@ -2834,3 +2763,20 @@ apps/workflow/management/commands/backport_data_backup.py:0: error: Call to unty apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] From 8c83c95076ece815c8b7d77f24b373953cd27475 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 13:16:19 +1200 Subject: [PATCH 25/39] KAN-316 test: use BaseAPITestCase for company-defaults API tests Both classes inherited BaseTestCase and reassigned self.client = APIClient(), so mypy still saw Django's Client and flagged force_authenticate and response.data. Inheriting BaseAPITestCase types self.client as DRF's APIClient, which removes the redundant assignment and the attr-defined errors. Also tighten a few Optional payloads in the schema tests with assert-narrowing and a list[str] annotation. --- .../tests/test_company_defaults_api.py | 6 ++--- .../tests/test_company_defaults_schema.py | 18 +++++++------- mypy-baseline.txt | 24 ------------------- 3 files changed, 11 insertions(+), 37 deletions(-) diff --git a/apps/workflow/tests/test_company_defaults_api.py b/apps/workflow/tests/test_company_defaults_api.py index c5ccca580..75cc22506 100644 --- a/apps/workflow/tests/test_company_defaults_api.py +++ b/apps/workflow/tests/test_company_defaults_api.py @@ -5,13 +5,13 @@ from rest_framework import status from rest_framework.test import APIClient -from apps.testing import BaseTestCase +from apps.testing import BaseAPITestCase from apps.workflow.models import CompanyDefaults -class CompanyDefaultsAPITests(BaseTestCase): +class CompanyDefaultsAPITests(BaseAPITestCase): def setUp(self) -> None: - self.client = APIClient() + super().setUp() self.client.force_authenticate(user=self.test_staff) def test_get_returns_shop_company_fk_without_name_alias(self) -> None: diff --git a/apps/workflow/tests/test_company_defaults_schema.py b/apps/workflow/tests/test_company_defaults_schema.py index 13df43769..388d7303b 100644 --- a/apps/workflow/tests/test_company_defaults_schema.py +++ b/apps/workflow/tests/test_company_defaults_schema.py @@ -5,10 +5,9 @@ from django.db import models from django.test import TestCase from rest_framework import status -from rest_framework.test import APIClient from apps.accounts.models import Staff -from apps.testing import BaseTestCase +from apps.testing import BaseAPITestCase from apps.workflow.models import CompanyDefaults from apps.workflow.models.settings_metadata import ( COMPANY_DEFAULTS_FIELD_SECTIONS, @@ -111,7 +110,7 @@ def test_settings_section_all_sections(self) -> None: def test_settings_section_get_section_info(self) -> None: """Test SettingsSection.get_section_info() returns correct info.""" info = SettingsSection.get_section_info("company") - self.assertIsNotNone(info) + assert info is not None self.assertEqual(info[0], "company") self.assertEqual(info[1], "Company") @@ -120,11 +119,11 @@ def test_settings_section_get_section_info(self) -> None: self.assertIsNone(info) -class CompanyDefaultsSchemaAPITests(BaseTestCase): +class CompanyDefaultsSchemaAPITests(BaseAPITestCase): """Test the schema API endpoint.""" def setUp(self) -> None: - self.client = APIClient() + super().setUp() self.staff = Staff.objects.create_user( email="test@example.com", password="testpassword123", @@ -170,7 +169,7 @@ def test_internal_fields_excluded(self) -> None: self.client.force_authenticate(user=self.staff) response = self.client.get("/api/company-defaults/schema/") - all_field_keys = [] + all_field_keys: list[str] = [] for section in response.data["sections"]: all_field_keys.extend(f["key"] for f in section["fields"]) @@ -218,16 +217,15 @@ def test_company_section_has_company_name(self) -> None: company_section = next( (s for s in response.data["sections"] if s["key"] == "company"), None ) - self.assertIsNotNone(company_section) + assert company_section is not None field_keys = [f["key"] for f in company_section["fields"]] self.assertIn("company_name", field_keys) def test_xero_section_exposes_sales_branding_theme_selector(self) -> None: """The theme is operable through Company Settings, not hidden config.""" - client = APIClient() - client.force_authenticate(user=self.staff) - response = client.get("/api/company-defaults/schema/") + self.client.force_authenticate(user=self.staff) + response = self.client.get("/api/company-defaults/schema/") payload = response.json() xero_section = next( diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 229de4c2d..96b6e28cc 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -1029,30 +1029,6 @@ apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | Non apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Argument "row_date" to "build_row" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "tuple[str, str, int] | None" is not indexable [index] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "tuple[str, str, int] | None" is not indexable [index] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Need type annotation for "all_field_keys" (hint: "all_field_keys: list[] = ...") [var-annotated] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "Client" has no attribute "force_authenticate" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_schema.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] -apps/workflow/tests/test_company_defaults_api.py:0: error: "_MonkeyPatchedWSGIResponse" has no attribute "data" [attr-defined] apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] From 794da519ceff347beea80f24bd6e08b18bdfbb03 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 14:25:56 +1200 Subject: [PATCH 26/39] KAN-316 test: address CodeRabbit review on PR 504 - Type sync_xero_data as Iterator[XeroSyncEvent] (reusing the existing TypedDict) and _consume likewise, so e.get("severity") checks against a real contract instead of object. - Widen the nullable override keys to match the models: xero_contact_id in the company builders and access_token/refresh_token in _active_app. - Keep the cast in the _job data-version helper but document why: the custom JobQuerySet.create() takes a staff= kwarg that is not a model field, so django-stubs can neither type its return nor accept the kwarg; annotating the manager trades the cast for a misc error and an internal no-any-return. --- .../tests/test_get_company_for_xero.py | 2 +- apps/workflow/api/xero/sync.py | 2 +- .../workflow/tests/test_data_versions_view.py | 4 +- apps/workflow/tests/test_push_contacts.py | 2 +- apps/workflow/tests/test_xero_quota_floor.py | 6 +- mypy-baseline.txt | 2802 ++++++++--------- 6 files changed, 1408 insertions(+), 1410 deletions(-) diff --git a/apps/company/tests/test_get_company_for_xero.py b/apps/company/tests/test_get_company_for_xero.py index 66fc72f93..6665db2e5 100644 --- a/apps/company/tests/test_get_company_for_xero.py +++ b/apps/company/tests/test_get_company_for_xero.py @@ -23,7 +23,7 @@ class _CompanyOverrides(TypedDict, total=False): email: str | None address: str | None xero_last_modified: datetime - xero_contact_id: str + xero_contact_id: str | None is_account_customer: bool phone: str | None diff --git a/apps/workflow/api/xero/sync.py b/apps/workflow/api/xero/sync.py index 0e8bf3184..c028961dd 100644 --- a/apps/workflow/api/xero/sync.py +++ b/apps/workflow/api/xero/sync.py @@ -160,7 +160,7 @@ def sync_xero_data( pagination_mode="single", xero_tenant_id=None, entity_key=None, -): +) -> Iterator[XeroSyncEvent]: """Sync data from Xero with pagination support. Args: diff --git a/apps/workflow/tests/test_data_versions_view.py b/apps/workflow/tests/test_data_versions_view.py index f55aae25e..609dc4149 100644 --- a/apps/workflow/tests/test_data_versions_view.py +++ b/apps/workflow/tests/test_data_versions_view.py @@ -99,7 +99,9 @@ def _job(staff: Staff, **overrides: Unpack[_JobOverrides]) -> Job: "pricing_methodology": "time_materials", } defaults.update(overrides) - # create() returns Any when fed Unpack kwargs; the row is always a Job. + # Job.objects.create() requires a staff= kwarg that is not a model field, so + # django-stubs cannot type it (Any result, "staff" rejected as an attribute). + # The custom manager always returns a Job; the cast states that contract. return cast(Job, Job.objects.create(staff=staff, **defaults)) diff --git a/apps/workflow/tests/test_push_contacts.py b/apps/workflow/tests/test_push_contacts.py index abffd38c0..568f77fe5 100644 --- a/apps/workflow/tests/test_push_contacts.py +++ b/apps/workflow/tests/test_push_contacts.py @@ -25,7 +25,7 @@ class _ClientOverrides(TypedDict, total=False): email: str | None address: str | None xero_last_modified: datetime - xero_contact_id: str + xero_contact_id: str | None phone: str | None diff --git a/apps/workflow/tests/test_xero_quota_floor.py b/apps/workflow/tests/test_xero_quota_floor.py index 84993f62f..3fba06a5f 100644 --- a/apps/workflow/tests/test_xero_quota_floor.py +++ b/apps/workflow/tests/test_xero_quota_floor.py @@ -27,7 +27,7 @@ from apps.company.models import Company from apps.purchasing.models import Stock from apps.workflow.api.xero.client import quota_floor_breached -from apps.workflow.api.xero.sync import sync_xero_data +from apps.workflow.api.xero.sync import XeroSyncEvent, sync_xero_data from apps.workflow.exceptions import XeroQuotaFloorReached from apps.workflow.models import CompanyDefaults, XeroApp from apps.workflow.services.xero_sync_constants import SYNC_STATUS_KEY @@ -46,6 +46,8 @@ class _ActiveAppOverrides(TypedDict, total=False): client_secret: str redirect_uri: str is_active: bool + access_token: str | None + refresh_token: str | None day_remaining: int | None minute_remaining: int | None snapshot_at: datetime | None @@ -382,7 +384,7 @@ def setUp(self) -> None: # TestCase's per-test transaction rollback. _set_company_floor() - def _consume(self, generator: Iterator[object]) -> list[object]: + def _consume(self, generator: Iterator[XeroSyncEvent]) -> list[XeroSyncEvent]: """Fully iterate the generator and return its emitted events.""" return list(generator) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 96b6e28cc..46eae5f1a 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -30,6 +30,14 @@ apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generi apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/company/utils.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/services/geocoding_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] @@ -207,6 +215,96 @@ apps/purchasing/models.py:0: error: Call to untyped function "generate_po_number apps/purchasing/models.py:0: error: "PurchaseOrderLine" has no attribute "received_lines" [attr-defined] apps/purchasing/models.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] apps/purchasing/models.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_logo" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_header_info" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_supplier_info" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_line_items_table" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: List item 0 has incompatible type "Paragraph"; expected "str" [list-item] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: List item 1 has incompatible type "Paragraph"; expected "str" [list-item] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "PurchaseOrderPDFGenerator" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "generate" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_email_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/allocation_service.py:0: error: Function "builtins.any" is not valid as a type [valid-type] +apps/purchasing/services/allocation_service.py:0: note: Perhaps you meant "typing.Any" instead of "any"? +apps/purchasing/services/allocation_service.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/purchasing/services/allocation_service.py:0: error: Incompatible return value type (got "tuple[PurchaseOrderLine | None, Stock]", expected "tuple[PurchaseOrderLine, Stock | CostLine]") [return-value] +apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] +apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] +apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] +apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Call to untyped function "get_available_scrapers" in typed context [no-untyped-call] +apps/quoting/management/commands/run_scrapers.py:0: error: Argument 5 to "run_scraper" of "Command" has incompatible type "Any | None"; expected "bool" [arg-type] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] +apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] +apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int +apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T +apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] +apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_postrun" [attr-defined] docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_prerun" [attr-defined] docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_setup" untyped [untyped-decorator] @@ -215,8 +313,19 @@ apps/workflow/services/session_replay_service.py:0: error: Argument 1 to "Path" apps/workflow/services/session_replay_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/services/search_telemetry.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/services/search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/client.py:0: error: Class cannot subclass "RESTClientObject" (has type "Any") [misc] apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -255,46 +364,48 @@ apps/workflow/accounting/provider.py:0: error: Missing type arguments for generi apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/timesheet/services/xero_hours.py:0: error: Incompatible return value type (got "dict[str | None, Staff]", expected "dict[str, Staff]") [return-value] -apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_logo" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_header_info" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_supplier_info" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_line_items_table" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: List item 0 has incompatible type "Paragraph"; expected "str" [list-item] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: List item 1 has incompatible type "Paragraph"; expected "str" [list-item] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "PurchaseOrderPDFGenerator" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "generate" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_email_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/allocation_service.py:0: error: Function "builtins.any" is not valid as a type [valid-type] -apps/purchasing/services/allocation_service.py:0: note: Perhaps you meant "typing.Any" instead of "any"? -apps/purchasing/services/allocation_service.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/purchasing/services/allocation_service.py:0: error: Incompatible return value type (got "tuple[PurchaseOrderLine | None, Stock]", expected "tuple[PurchaseOrderLine, Stock | CostLine]") [return-value] -apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: note: Use "-> None" if function does not return a value +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "CostLine") [assignment] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "Decimal") [assignment] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Argument 4 to "_split_costline" of "Command" has incompatible type "Decimal | CostLine | str | Any"; expected "str" [arg-type] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "date | Decimal | CostSet | Staff | str | Any", variable has type "Staff") [assignment] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "cost_set" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "CostSet | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "quantity" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "accounting_date" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | date | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "str" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] +apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] -apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "xero_id" [union-attr] apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr] apps/job/services/time_entry_rates.py:0: error: Incompatible return value type (got "Any | None", expected "XeroPayItem") [return-value] @@ -353,6 +464,18 @@ apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "find apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/importers/google_sheets.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Argument 3 to "_upload_to_google_docs" of "Command" has incompatible type "str | None"; expected "str" [arg-type] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Incompatible types in assignment (expression has type "Procedure", variable has type "Form") [assignment] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Need type annotation for "candidates" (hint: "candidates: dict[, ] = ...") [var-annotated] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "_get_drive_service" in typed context [no-untyped-call] apps/crm/services/phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] apps/crm/services/phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounting/services/sales_pipeline_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] @@ -368,16 +491,35 @@ apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid ind apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] apps/accounting/services/invoice_calculation.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] +apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] +apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] +apps/workflow/services/llm_service.py:0: note: Possible overload variants: +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str +apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/services/dev_demo_export_scrubber.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] @@ -388,73 +530,13 @@ apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped functi apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Call to untyped function "get_available_scrapers" in typed context [no-untyped-call] -apps/quoting/management/commands/run_scrapers.py:0: error: Argument 5 to "run_scraper" of "Command" has incompatible type "Any | None"; expected "bool" [arg-type] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "CostLine") [assignment] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "Decimal") [assignment] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Argument 4 to "_split_costline" of "Command" has incompatible type "Decimal | CostLine | str | Any"; expected "str" [arg-type] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "date | Decimal | CostSet | Staff | str | Any", variable has type "Staff") [assignment] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "cost_set" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "CostSet | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "quantity" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "accounting_date" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | date | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "str" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -495,10 +577,9 @@ apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase apps/quoting/mcp.py:0: error: Need type annotation for "supplier_prices" (hint: "supplier_prices: dict[, ] = ...") [var-annotated] -apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] -apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/services/form_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/form_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] apps/operations/services/scheduler_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] @@ -570,210 +651,153 @@ apps/process/services/google_docs_service.py:0: error: Missing type arguments fo apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Argument 3 to "_upload_to_google_docs" of "Command" has incompatible type "str | None"; expected "str" [arg-type] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Incompatible types in assignment (expression has type "Procedure", variable has type "Form") [assignment] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Need type annotation for "candidates" (hint: "candidates: dict[, ] = ...") [var-annotated] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "_get_drive_service" in typed context [no-untyped-call] apps/workflow/services/db_scrubber.py:0: error: Argument 1 to "add" of "set" has incompatible type "str | None"; expected "str" [arg-type] apps/job/services/data_integrity_service.py:0: error: Dict entry 4 has incompatible type "str": "list[str]"; expected "str": "str" [dict-item] apps/job/services/data_integrity_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value -apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] -apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] -apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] -apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_determine_status" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_get_staff_alerts" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Decimal") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Argument 2 to "_get_color" of "KPIService" has incompatible type "Decimal"; expected "float" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Argument "key" to "max" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/accounting/services/core.py:0: error: Argument 1 to "localtime" has incompatible type "object"; expected "datetime | None" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "date") [assignment] -apps/accounting/services/core.py:0: error: Incompatible return value type (got "None", expected "dict[str, Any]") [return-value] -apps/accounting/services/core.py:0: error: Generator has incompatible item type "Decimal"; expected "bool" [misc] -apps/accounting/services/core.py:0: error: "CostLine" has no attribute "is_billable_meta" [attr-defined] -apps/accounting/services/core.py:0: error: Argument 1 to "_calculate_job_breakdown" of "StaffPerformanceService" has incompatible type "list[CostLine]"; expected "QuerySet[Any, Any]" [arg-type] -apps/accounting/services/core.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "float") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for / ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for / ("str" and "float") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for / ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] +apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] +apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance +apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] +apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -875,8 +899,6 @@ apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing ty apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -889,84 +911,12 @@ apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing t apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/accounting/serializers/rdti_spend_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] -apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] -apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance -apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] -apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/views/data_versions_view.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/views/build_id_view.py:0: error: Missing type arguments for generic type "list" [type-arg] apps/workflow/api/reports/pnl.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1029,46 +979,101 @@ apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | Non apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] apps/accounting/views/sales_forecast_view.py:0: error: Argument "row_date" to "build_row" has incompatible type "Any | None"; expected "str" [arg-type] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_jobs_api_filter.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/tests/test_jobs_api_filter.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/timesheet/tests/test_jobs_api_filter.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] +apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] +apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value +apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value +apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] +apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] +apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] +apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] +apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "return_value" [attr-defined] +apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "assert_called_once_with" [attr-defined] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/timesheet/tests/test_jobs_api_filter.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/tests/test_jobs_api_filter.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/timesheet/tests/test_jobs_api_filter.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_make_special_leave_job" in typed context [no-untyped-call] apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_book_time" in typed context [no-untyped-call] @@ -1128,9 +1133,41 @@ apps/accounting/tests/test_sales_pipeline_api.py:0: error: "type[SalesPipelineAP apps/accounting/tests/test_sales_pipeline_api.py:0: error: "SalesPipelineAPITests" has no attribute "office_staff" [attr-defined] apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/accounting/tests/test_sales_pipeline_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] -apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_kanban_search.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] +apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] +apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/serializers.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1170,10 +1207,60 @@ apps/workflow/serializers.py:0: error: Missing type arguments for generic type " apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1199,6 +1286,20 @@ apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_files_collection_view.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Call to untyped function "save_file" in typed context [no-untyped-call] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_thumbnail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] @@ -1222,6 +1323,9 @@ apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1236,336 +1340,9 @@ apps/company/serializers.py:0: error: Missing type arguments for generic type "S apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] -apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] -apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Call to untyped function "get_job_by_number" in typed context [no-untyped-call] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_files_collection_view.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Call to untyped function "save_file" in typed context [no-untyped-call] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_thumbnail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobSummaryDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "bool | None" [no-any-return] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Argument "choices" to "ChoiceField" has incompatible type "Sequence[tuple[Any, Any]] | Sequence[tuple[str, Iterable[tuple[Any, Any]]]] | None"; expected "Sequence[Any]" [arg-type] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "BindingDict") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -1573,473 +1350,304 @@ apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is miss apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/workshop_pdf_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "id" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "meta" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "quantity" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "unit_cost" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "calculated_total_cost" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostSet | None" has no attribute "rev" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/delivery_docket_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] -apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] -apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] -apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] -apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Staff | AnonymousUser") [assignment] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] -apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] -apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/kanban_view_api.py:0: error: "str" has no attribute "HTTP_500_INTERNAL_SERVER_ERROR" [attr-defined] -apps/job/views/kanban_view_api.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: "JobQuoteChatSerializer" has no attribute "get" [attr-defined] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Call to untyped function "_archive_quote_data" in typed context [no-untyped-call] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] -apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_staff_from_job" of "JobStaffService" in typed context [no-untyped-call] -apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] -apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] -apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] -apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] -apps/job/services/job_rest_service.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/services/job_rest_service.py:0: error: Argument "key" to "sort" of "list" has incompatible type "Callable[[dict[str, int | datetime | UUID | str | Any | None]], int | datetime | UUID | str | Any | None]"; expected "Callable[[dict[str, int | datetime | UUID | str | Any | None]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "int | datetime | UUID | str | Any | None", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/job/services/job_rest_service.py:0: error: Incompatible default for parameter "week" (default has type "None", parameter has type "date") [assignment] -apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] -apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Argument 1 to "get_weekly_metrics" of "JobRestService" has incompatible type "date | None"; expected "date" [arg-type] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: "type[Job]" has no attribute "STATUS_CHOICES" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] -apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] -apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] -apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] -apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] -apps/workflow/services/llm_service.py:0: note: Possible overload variants: -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str -apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value -apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] -apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] +apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] +apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_determine_status" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_get_staff_alerts" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] +apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Decimal") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Argument 2 to "_get_color" of "KPIService" has incompatible type "Decimal"; expected "float" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Argument "key" to "max" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/accounting/services/core.py:0: error: Argument 1 to "localtime" has incompatible type "object"; expected "datetime | None" [arg-type] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "date") [assignment] +apps/accounting/services/core.py:0: error: Incompatible return value type (got "None", expected "dict[str, Any]") [return-value] +apps/accounting/services/core.py:0: error: Generator has incompatible item type "Decimal"; expected "bool" [misc] +apps/accounting/services/core.py:0: error: "CostLine" has no attribute "is_billable_meta" [attr-defined] +apps/accounting/services/core.py:0: error: Argument 1 to "_calculate_job_breakdown" of "StaffPerformanceService" has incompatible type "list[CostLine]"; expected "QuerySet[Any, Any]" [arg-type] +apps/accounting/services/core.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for / ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for / ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for / ("str") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] +apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] apps/job/services/chat_service.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] apps/job/services/chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] apps/job/services/chat_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] apps/job/services/chat_service.py:0: error: Cannot call function of unknown type [operator] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] +apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] +apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Need type annotation for "updated_line_ids" (hint: "updated_line_ids: set[] = ...") [var-annotated] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] +apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Call to untyped function "get_job_by_number" in typed context [no-untyped-call] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] @@ -2091,27 +1699,362 @@ apps/process/views/procedure_viewsets.py:0: error: Function is missing a type an apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "return_value" [attr-defined] -apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "assert_called_once_with" [attr-defined] -apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] -apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobSummaryDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "bool | None" [no-any-return] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Argument "choices" to "ChoiceField" has incompatible type "Sequence[tuple[Any, Any]] | Sequence[tuple[str, Iterable[tuple[Any, Any]]]] | None"; expected "Sequence[Any]" [arg-type] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "BindingDict") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/views/workshop_pdf_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "id" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "meta" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "quantity" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "unit_cost" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "calculated_total_cost" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostSet | None" has no attribute "rev" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/delivery_docket_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] +apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] +apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] +apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] +apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] +apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_none_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Need type annotation for "allocations_by_line" (hint: "allocations_by_line: dict[, ] = ...") [var-annotated] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "PurchaseOrderLine | None" has no attribute "id" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Generator has incompatible item type "int"; expected "bool" [misc] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "create_purchase_order_pdf" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Staff | AnonymousUser") [assignment] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] apps/workflow/api/xero/auth.py:0: error: Call to untyped function "RateLimitedRESTClient" in typed context [no-untyped-call] apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] @@ -2247,7 +2190,7 @@ apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_last_modified_time" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "update_sync_cursor" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] @@ -2260,7 +2203,6 @@ apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_sync_cursor" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_local_stock_to_xero" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2284,41 +2226,6 @@ apps/workflow/api/xero/seed.py:0: error: Call to untyped function "_resolve_api_ apps/workflow/api/xero/seed.py:0: error: Dict entry 0 has incompatible type "str": "int"; expected "str": "str" [dict-item] apps/workflow/api/xero/seed.py:0: error: Argument 1 to "update" of "MutableMapping" has incompatible type "dict[str, str] | dict[str, bool]"; expected "SupportsKeysAndGetItem[str, str]" [arg-type] apps/workflow/api/xero/seed.py:0: error: Incompatible types in assignment (expression has type "int", target has type "str") [assignment] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] -apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] apps/workflow/views/xero_apps_view.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2362,6 +2269,85 @@ apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "syn apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/kanban_view_api.py:0: error: "str" has no attribute "HTTP_500_INTERNAL_SERVER_ERROR" [attr-defined] +apps/job/views/kanban_view_api.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: "JobQuoteChatSerializer" has no attribute "get" [attr-defined] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Call to untyped function "_archive_quote_data" in typed context [no-untyped-call] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] +apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_staff_from_job" of "JobStaffService" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2450,33 +2436,110 @@ apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Need type annotation for "updated_line_ids" (hint: "updated_line_ids: set[] = ...") [var-annotated] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] -apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] -apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] -apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int -apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T -apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] +apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] +apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] +apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] +apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] +apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] +apps/job/services/job_rest_service.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/services/job_rest_service.py:0: error: Argument "key" to "sort" of "list" has incompatible type "Callable[[dict[str, int | datetime | UUID | str | Any | None]], int | datetime | UUID | str | Any | None]"; expected "Callable[[dict[str, int | datetime | UUID | str | Any | None]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "int | datetime | UUID | str | Any | None", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/job/services/job_rest_service.py:0: error: Incompatible default for parameter "week" (default has type "None", parameter has type "date") [assignment] +apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Argument 1 to "get_weekly_metrics" of "JobRestService" has incompatible type "date | None"; expected "date" [arg-type] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: "type[Job]" has no attribute "STATUS_CHOICES" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_contact" in typed context [no-untyped-call] apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_invoice" in typed context [no-untyped-call] +apps/workflow/tests/test_celery_setup.py:0: error: "Celery" has no attribute "main" [attr-defined] +apps/workflow/tests/test_celery_setup.py:0: error: "Celery" has no attribute "tasks" [attr-defined] +apps/workflow/tests/test_celery_setup.py:0: error: "Callable[[], str]" has no attribute "apply" [attr-defined] +apps/workflow/tests/test_celery_setup.py:0: error: "Signal" has no attribute "send" [attr-defined] +apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] @@ -2521,84 +2584,6 @@ apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annot apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] -apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_none_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Need type annotation for "allocations_by_line" (hint: "allocations_by_line: dict[, ] = ...") [var-annotated] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "PurchaseOrderLine | None" has no attribute "id" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Generator has incompatible item type "int"; expected "bool" [misc] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "create_purchase_order_pdf" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] -apps/workflow/xero_webhooks.py:0: error: "Callable[[str, dict[str, Any]], None]" has no attribute "delay" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "sync_xero_data" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: "object" has no attribute "get" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Unexpected keyword argument "access_token" for "_active_app" [call-arg] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Unexpected keyword argument "refresh_token" for "_active_app" [call-arg] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.api.xero.stock_sync" does not explicitly export attribute "XeroAccount" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_gen" in typed context [no-untyped-call] -apps/workflow/tests/test_tasks.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] -apps/workflow/tests/test_celery_setup.py:0: error: "Celery" has no attribute "main" [attr-defined] -apps/workflow/tests/test_celery_setup.py:0: error: "Celery" has no attribute "tasks" [attr-defined] -apps/workflow/tests/test_celery_setup.py:0: error: "Callable[[], str]" has no attribute "apply" [attr-defined] -apps/workflow/tests/test_celery_setup.py:0: error: "Signal" has no attribute "send" [attr-defined] -apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_xero_po_manager.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "supplier" [attr-defined] apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "purchase_order" [attr-defined] @@ -2606,6 +2591,13 @@ apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderMan apps/workflow/tests/test_xero_po_manager.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_po_manager.py:0: error: "XeroPurchaseOrderManagerConstructionTests" has no attribute "purchase_order" [attr-defined] apps/workflow/tests/test_xero_app_active.py:0: error: Value of type "dict[str, Any] | None" is not indexable [index] +apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] @@ -2654,10 +2646,27 @@ apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to u apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Incompatible types in assignment (expression has type "StringIO", variable has type "OutputWrapper") [assignment] apps/workflow/tests/test_seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/workflow/xero_webhooks.py:0: error: "Callable[[str, dict[str, Any]], None]" has no attribute "delay" [attr-defined] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_handle_rate_limit" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.api.xero.stock_sync" does not explicitly export attribute "XeroAccount" [attr-defined] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_gen" in typed context [no-untyped-call] +apps/workflow/tests/test_tasks.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2700,13 +2709,15 @@ apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a retu apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/tests/test_xero_setup_command.py:0: error: Cannot assign to a method [method-assign] +apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] @@ -2739,20 +2750,3 @@ apps/workflow/management/commands/backport_data_backup.py:0: error: Call to unty apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] From 03b7e1312906d857944055c71be247cf3942c16a Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 14:30:56 +1200 Subject: [PATCH 27/39] chore: sort mypy-baseline so syncs diff cleanly mypy-baseline stores entries in mypy's output order, which shifts whenever code changes perturb module processing order, so every sync rewrote the whole file and buried the real add/remove in reorder churn. Adopt the tool's --sort-baseline flag in the documented sync command (check_mypy.sh, CLAUDE.md) and re-sort the existing baseline once. The re-sort is a pure reorder (no entries added or removed); the filter gate is order-independent and still passes. --- CLAUDE.md | 2 +- mypy-baseline.txt | 5092 ++++++++++++++++++++--------------------- scripts/check_mypy.sh | 4 +- 3 files changed, 2550 insertions(+), 2548 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8d20827fe..7180fd457 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -154,7 +154,7 @@ Ratchet rules: - ADR 0028: type annotations are data contracts. Touched code must improve mypy by preserving or tightening the real contract; no `Any`, fake `| None`, broad unions, casts, or ignores as checker shortcuts. - ADR 0028 also treats broad `object`, fallback-style `dict.get()`, `hasattr()` contract probes, and happy-case-first branching as soft smells; prefer named types, explicit contracts, direct access after validation, and bad-case guards. - If a touched type becomes hard to read, introduce a named type (`dataclass`, `TypedDict`, protocol, or alias) instead of repeating a complex inline annotation. -- After fixing baselined errors, run `poetry run mypy apps/ docketworks/ | poetry run mypy-baseline sync` and commit the shrunken baseline in the same PR. +- After fixing baselined errors, run `poetry run mypy apps/ docketworks/ | poetry run mypy-baseline sync --sort-baseline` and commit the shrunken baseline in the same PR. `--sort-baseline` keeps the file in canonical order so the diff shows only real add/remove, not mypy's output-order reshuffling. - `# type: ignore[code]` requires the specific error code and a justification comment on the same line. ### Defensive programming diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 46eae5f1a..471ce09cf 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -1,133 +1,392 @@ -apps/job/services/kanban_categorization_service.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/job/services/kanban_categorization_service.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/tests/fixtures/xero_responses.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] -apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.InvoicePayload.date" is not valid as a type [valid-type] -apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases -apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] -apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.QuotePayload.date" is not valid as a type [valid-type] -apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases -apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] -apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.POPayload.date" is not valid as a type [valid-type] -apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases -apps/workflow/accounting/types.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/types.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_helpers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_helpers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] -apps/workflow/api/reports/utils.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/services/validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/validation.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/validation.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/quoting/services/providers/common.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/delta_checksum.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "Decimal") [assignment] -apps/job/services/delta_checksum.py:0: error: Argument 1 to "join" of "str" has incompatible type "Decimal"; expected "Iterable[str]" [arg-type] -apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/company/utils.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/services/geocoding_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "split" [union-attr] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "split" [union-attr] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "rstrip" [union-attr] -docketworks/settings.py:0: error: Argument 1 to "int" has incompatible type "str | None"; expected "str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "int" has incompatible type "str | None"; expected "str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "int" has incompatible type "str | None"; expected "str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] -docketworks/settings.py:0: error: Argument 1 to "int" has incompatible type "str | None"; expected "str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc" [arg-type] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] -docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "split" [union-attr] -docketworks/settings.py:0: error: Function is missing a return type annotation [no-untyped-def] -docketworks/settings.py:0: note: Use "-> None" if function does not return a value -docketworks/settings.py:0: error: Function is missing a type annotation [no-untyped-def] -docketworks/settings.py:0: error: Call to untyped function "configure_site_for_environment" in typed context [no-untyped-call] -apps/workflow/models/service_api_key.py:0: error: Call to untyped function "generate_api_key" of "ServiceAPIKey" in typed context [no-untyped-call] -apps/workflow/models/service_api_key.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/job/models/spreadsheet.py:0: error: Item "None" of "Job | None" has no attribute "job_number" [union-attr] -apps/accounting/models/invoice.py:0: error: Incompatible return value type (got "int | Decimal", expected "Decimal") [return-value] -apps/accounting/models/invoice.py:0: error: Generator has incompatible item type "Any | Decimal"; expected "bool" [misc] apps/accounting/models/invoice.py:0: error: "BaseXeroInvoiceDocument" has no attribute "line_items" [attr-defined] -apps/job/helpers.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/company/models.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/company/models.py:0: error: Incompatible type for lookup 'company_id': (got "UUID | None", expected "UUID | str") [misc] -apps/company/models.py:0: error: Need type annotation for "SUPPLIERPICKUPADDRESS_INTERNAL_FIELDS" (hint: "SUPPLIERPICKUPADDRESS_INTERNAL_FIELDS: list[] = ...") [var-annotated] -apps/job/services/file_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/file_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/file_service.py:0: error: Incompatible types in assignment (expression has type "Image", variable has type "ImageFile") [assignment] -apps/job/services/file_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/file_service.py:0: error: Call to untyped function "get_thumbnail_folder" in typed context [no-untyped-call] -apps/job/services/file_service.py:0: error: Call to untyped function "create_thumbnail" in typed context [no-untyped-call] -apps/job/models/costing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/models/costing.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/models/costing.py:0: error: "type[Model]" has no attribute "objects" [attr-defined] -apps/job/models/costing.py:0: error: Call to untyped function "_save_with_summary_update" in typed context [no-untyped-call] +apps/accounting/models/invoice.py:0: error: Generator has incompatible item type "Any | Decimal"; expected "bool" [misc] +apps/accounting/models/invoice.py:0: error: Incompatible return value type (got "int | Decimal", expected "Decimal") [return-value] +apps/accounting/serializers/rdti_spend_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] +apps/accounting/services/core.py:0: error: "CostLine" has no attribute "is_billable_meta" [attr-defined] +apps/accounting/services/core.py:0: error: Argument "key" to "max" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/accounting/services/core.py:0: error: Argument 1 to "_calculate_job_breakdown" of "StaffPerformanceService" has incompatible type "list[CostLine]"; expected "QuerySet[Any, Any]" [arg-type] +apps/accounting/services/core.py:0: error: Argument 1 to "localtime" has incompatible type "object"; expected "datetime | None" [arg-type] +apps/accounting/services/core.py:0: error: Argument 2 to "_get_color" of "KPIService" has incompatible type "Decimal"; expected "float" [arg-type] +apps/accounting/services/core.py:0: error: Generator has incompatible item type "Decimal"; expected "bool" [misc] +apps/accounting/services/core.py:0: error: Incompatible return value type (got "None", expected "dict[str, Any]") [return-value] +apps/accounting/services/core.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Decimal") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "date") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/core.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] +apps/accounting/services/core.py:0: error: Unsupported left operand type for / ("str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "Decimal") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for / ("float" and "str") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for / ("str" and "float") [operator] +apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: note: Both left and right operands are unions +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" +apps/accounting/services/invoice_calculation.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] +apps/accounting/services/payroll_reconciliation_service.py:0: error: Key expression in dictionary comprehension has incompatible type "str | None"; expected type "str" [misc] +apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types in assignment (expression has type "float | None", target has type "float") [assignment] +apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types in assignment (expression has type "float | None", target has type "float") [assignment] +apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types in assignment (expression has type "float | None", target has type "float") [assignment] +apps/accounting/services/sales_pipeline_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/accounting/services/sales_pipeline_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounting/services/sales_pipeline_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] +apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: "SalesPipelineAPITests" has no attribute "office_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: "type[SalesPipelineAPITests]" has no attribute "office_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounting/tests/test_sales_pipeline_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] +apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/accounting/views/sales_forecast_view.py:0: error: Argument "row_date" to "build_row" has incompatible type "Any | None"; expected "str" [arg-type] +apps/accounting/views/sales_forecast_view.py:0: error: Argument 1 to "_get_total_invoiced_for_job" of "SalesForecastMonthDetailAPIView" has incompatible type "Job | None"; expected "Job" [arg-type] +apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Company | Any | None" has no attribute "name" [union-attr] +apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "company" [union-attr] +apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "job_number" [union-attr] +apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "latest_actual" [union-attr] +apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "start_date" [union-attr] apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] -apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "EmailField[str | Combinable, str]", variable has type "str") [assignment] -apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "CharField[str | int | Combinable, str]", variable has type "str") [assignment] -apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "CharField[str | int | Combinable, str]", variable has type "str") [assignment] -apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "CharField[str | int | Combinable | None, str | None]", variable has type "str | None") [assignment] apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] +apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "CharField[str | int | Combinable | None, str | None]", variable has type "str | None") [assignment] +apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "CharField[str | int | Combinable, str]", variable has type "str") [assignment] +apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "CharField[str | int | Combinable, str]", variable has type "str") [assignment] apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "DateTimeField[str | datetime | date | Combinable, datetime]", variable has type "datetime") [assignment] -apps/job/models/job_file.py:0: error: Argument 1 to "get_job_folder_path" has incompatible type "int"; expected "str" [arg-type] -apps/job/models/job_file.py:0: error: Call to untyped function "get_thumbnail_folder" in typed context [no-untyped-call] -apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] -apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] -apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] -apps/job/models/job_event.py:0: error: Argument 1 to "_format_status" has incompatible type "Any | None"; expected "str" [arg-type] -apps/job/models/job_event.py:0: error: Unsupported left operand type for < ("None") [operator] -apps/job/models/job_event.py:0: note: Both left and right operands are unions -apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] -apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] -apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/models.py:0: error: Incompatible types in assignment (expression has type "EmailField[str | Combinable, str]", variable has type "str") [assignment] +apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/staff_anonymization.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] +apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/models.py:0: error: Incompatible type for lookup 'company_id': (got "UUID | None", expected "UUID | str") [misc] +apps/company/models.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/company/models.py:0: error: Need type annotation for "SUPPLIERPICKUPADDRESS_INTERNAL_FIELDS" (hint: "SUPPLIERPICKUPADDRESS_INTERNAL_FIELDS: list[] = ...") [var-annotated] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] +apps/company/services/geocoding_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/tests/test_company_fts_search.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Staff | AnonymousUser") [assignment] +apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/tests/test_company_merge_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/company/tests/test_company_merge_service.py:0: error: Value of type "Any | None" is not indexable [index] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] +apps/company/utils.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] +apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/crm/services/phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/crm/services/phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] +apps/crm/tests/test_phone_call_service.py:0: error: Cannot assign to a method [method-assign] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] +apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] +apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] +apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] +apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/job/helpers.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/importers/google_sheets.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: "object" has no attribute "update" [attr-defined] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "detect_labour_column" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "detect_labour_column" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "detect_material_columns" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "detect_material_columns" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "find_validation_cells" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "find_validation_cells" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "validate_totals" in typed context [no-untyped-call] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/importers/quote_spreadsheet.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "ValidationError") [assignment] +apps/job/importers/quote_spreadsheet.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/importers/quote_spreadsheet.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/importers/quote_spreadsheet.py:0: error: Need type annotation for "conflicts" (hint: "conflicts: list[] = ...") [var-annotated] +apps/job/importers/quote_spreadsheet.py:0: error: Need type annotation for "errors" (hint: "errors: list[] = ...") [var-annotated] +apps/job/importers/quote_spreadsheet.py:0: error: Need type annotation for "warnings" (hint: "warnings: list[] = ...") [var-annotated] +apps/job/importers/quote_spreadsheet.py:0: error: Unsupported target for indexed assignment ("object") [index] +apps/job/importers/quote_spreadsheet.py:0: error: Unsupported target for indexed assignment ("object") [index] +apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Call to untyped function "get_job_by_number" in typed context [no-untyped-call] +apps/job/mixins.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] +apps/job/models/costing.py:0: error: "type[Model]" has no attribute "objects" [attr-defined] +apps/job/models/costing.py:0: error: Call to untyped function "_save_with_summary_update" in typed context [no-untyped-call] +apps/job/models/costing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/models/costing.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: "Callable[[Any, Any], Any]" has no attribute "__func__" [attr-defined] +apps/job/models/job.py:0: error: Call to untyped function "_apply_change_side_effects" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Call to untyped function "_clear_assigned_staff_on_archive" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Call to untyped function "_detect_field_changes" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Call to untyped function "_infer_event_type" of "Job" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Call to untyped function "_json_safe" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Call to untyped function "_json_safe" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Call to untyped function "_json_safe" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Call to untyped function "_json_safe" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Call to untyped function "_record_change_event" in typed context [no-untyped-call] +apps/job/models/job.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] +apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] +apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] +apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] +apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "DateTimeField[str | datetime | date | Combinable | None, datetime | None]", variable has type "datetime | None") [assignment] +apps/job/models/job.py:0: error: Item "ForeignObjectRel" of "Field[Any, Any] | ForeignObjectRel" has no attribute "verbose_name" [union-attr] +apps/job/models/job.py:0: error: Item "None" of "str | None" has no attribute "rstrip" [union-attr] +apps/job/models/job.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] +apps/job/models/job.py:0: error: Returning Any from function declared to return "date | None" [no-any-return] +apps/job/models/job.py:0: error: Returning Any from function declared to return "date | None" [no-any-return] apps/job/models/job_event.py:0: error: "Callable[[dict[Any, Any]], str]" has no attribute "__func__" [attr-defined] apps/job/models/job_event.py:0: error: "Callable[[dict[Any, Any]], str]" has no attribute "__func__" [attr-defined] apps/job/models/job_event.py:0: error: "Callable[[dict[Any, Any]], str]" has no attribute "__func__" [attr-defined] @@ -150,1714 +409,860 @@ apps/job/models/job_event.py:0: error: "Callable[[dict[Any, Any]], str]" has no apps/job/models/job_event.py:0: error: "Callable[[dict[Any, Any]], str]" has no attribute "__func__" [attr-defined] apps/job/models/job_event.py:0: error: "Callable[[dict[Any, Any]], str]" has no attribute "__func__" [attr-defined] apps/job/models/job_event.py:0: error: "Callable[[dict[Any, Any]], str]" has no attribute "__func__" [attr-defined] -apps/job/models/job_event.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/services/error_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/error_persistence.py:0: error: Item "None" of "FrameType | None" has no attribute "f_back" [union-attr] -apps/workflow/services/error_persistence.py:0: error: Item "None" of "FrameType | Any | None" has no attribute "f_back" [union-attr] -apps/workflow/services/error_persistence.py:0: error: Item "None" of "FrameType | Any | None" has no attribute "f_code" [union-attr] -apps/workflow/services/error_persistence.py:0: error: Item "None" of "FrameType | Any | None" has no attribute "f_code" [union-attr] -apps/workflow/services/error_persistence.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/services/error_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/error_persistence.py:0: error: Incompatible type for "reference_id" of "XeroError" (got "str | None", expected "str | int | Combinable") [misc] -apps/workflow/services/error_persistence.py:0: error: Call to untyped function "_extract_caller_context" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "DateTimeField[str | datetime | date | Combinable | None, datetime | None]", variable has type "datetime | None") [assignment] -apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] -apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] -apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] -apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] -apps/job/models/job.py:0: error: Item "None" of "str | None" has no attribute "rstrip" [union-attr] -apps/job/models/job.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/models/job.py:0: error: Returning Any from function declared to return "date | None" [no-any-return] -apps/job/models/job.py:0: error: Returning Any from function declared to return "date | None" [no-any-return] -apps/job/models/job.py:0: error: Call to untyped function "_detect_field_changes" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Call to untyped function "_apply_change_side_effects" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Call to untyped function "_record_change_event" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Call to untyped function "_clear_assigned_staff_on_archive" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Call to untyped function "_json_safe" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Call to untyped function "_json_safe" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Item "ForeignObjectRel" of "Field[Any, Any] | ForeignObjectRel" has no attribute "verbose_name" [union-attr] -apps/job/models/job.py:0: error: Call to untyped function "_json_safe" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Call to untyped function "_json_safe" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: Call to untyped function "_infer_event_type" of "Job" in typed context [no-untyped-call] -apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/models/job.py:0: error: "Callable[[Any, Any, Any], Any]" has no attribute "__func__" [attr-defined] -apps/job/tasks.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/tasks.py:0: error: Call to untyped function "get_thumbnail_folder" in typed context [no-untyped-call] -apps/job/tasks.py:0: error: Call to untyped function "create_thumbnail" in typed context [no-untyped-call] -apps/job/services/workshop_pdf_service.py:0: error: Module "bs4" does not explicitly export attribute "NavigableString" [attr-defined] -apps/job/services/workshop_pdf_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/workshop_pdf_service.py:0: error: Need type annotation for "staff_hours" [var-annotated] -apps/job/services/workshop_pdf_service.py:0: error: Incompatible types in assignment (expression has type "list[Table | Flowable]", variable has type "list[Table]") [assignment] -apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "wait_until_file_ready" in typed context [no-untyped-call] -apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_letterhead_banner" in typed context [no-untyped-call] -apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_handover_section" in typed context [no-untyped-call] -apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_letterhead_banner" in typed context [no-untyped-call] -apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_handover_section" in typed context [no-untyped-call] -apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_pdf_service.py:0: error: Argument 1 to "Table" has incompatible type "list[object]"; expected "Sequence[list[Any] | tuple[Any, ...]]" [arg-type] -apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/workshop_pdf_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/services/workshop_pdf_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/models.py:0: error: Call to untyped function "generate_po_number" in typed context [no-untyped-call] -apps/purchasing/models.py:0: error: "PurchaseOrderLine" has no attribute "received_lines" [attr-defined] -apps/purchasing/models.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/models.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_logo" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_header_info" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_supplier_info" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_line_items_table" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: List item 0 has incompatible type "Paragraph"; expected "str" [list-item] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: List item 1 has incompatible type "Paragraph"; expected "str" [list-item] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "PurchaseOrderPDFGenerator" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "generate" in typed context [no-untyped-call] -apps/purchasing/services/purchase_order_email_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/allocation_service.py:0: error: Function "builtins.any" is not valid as a type [valid-type] -apps/purchasing/services/allocation_service.py:0: note: Perhaps you meant "typing.Any" instead of "any"? -apps/purchasing/services/allocation_service.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/purchasing/services/allocation_service.py:0: error: Incompatible return value type (got "tuple[PurchaseOrderLine | None, Stock]", expected "tuple[PurchaseOrderLine, Stock | CostLine]") [return-value] -apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] -apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] -apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] -apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] -apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] -apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] -apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reassign_time_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Call to untyped function "get_available_scrapers" in typed context [no-untyped-call] -apps/quoting/management/commands/run_scrapers.py:0: error: Argument 5 to "run_scraper" of "Command" has incompatible type "Any | None"; expected "bool" [arg-type] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/set_paid_flag_jobs.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] -apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] -apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None -apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int -apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T -apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] -apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] -docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_postrun" [attr-defined] -docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_prerun" [attr-defined] -docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_setup" untyped [untyped-decorator] -docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_teardown" untyped [untyped-decorator] -apps/workflow/services/session_replay_service.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/services/session_replay_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/search_telemetry.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Class cannot subclass "RESTClientObject" (has type "Any") [misc] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_log_quota" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_record_quota" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_parse_int" of "RateLimitedRESTClient" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_parse_int" of "RateLimitedRESTClient" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_parse_int" of "RateLimitedRESTClient" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_maybe_log_threshold_warning" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_maybe_log_threshold_warning" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Call to untyped function "_log_summary" in typed context [no-untyped-call] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/timesheet/services/xero_hours.py:0: error: Incompatible return value type (got "dict[str | None, Staff]", expected "dict[str, Staff]") [return-value] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: note: Use "-> None" if function does not return a value -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "CostLine") [assignment] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "Decimal") [assignment] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Argument 4 to "_split_costline" of "Command" has incompatible type "Decimal | CostLine | str | Any"; expected "str" [arg-type] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "date | Decimal | CostSet | Staff | str | Any", variable has type "Staff") [assignment] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "cost_set" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "CostSet | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "quantity" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "accounting_date" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | date | Combinable") [misc] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "str" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] -apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] -apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/job/diff.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/diff.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "xero_id" [union-attr] -apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr] -apps/job/services/time_entry_rates.py:0: error: Incompatible return value type (got "Any | None", expected "XeroPayItem") [return-value] -apps/job/services/job_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/job_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/job_service.py:0: error: Call to untyped function "_touch_job_for_assignment_change" of "JobStaffService" in typed context [no-untyped-call] -apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/job_service.py:0: error: Call to untyped function "_touch_job_for_assignment_change" of "JobStaffService" in typed context [no-untyped-call] -apps/job/services/delivery_docket_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "detect_labour_column" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "detect_material_columns" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "validate_totals" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "find_validation_cells" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/importers/quote_spreadsheet.py:0: error: Unsupported target for indexed assignment ("object") [index] -apps/job/importers/quote_spreadsheet.py:0: error: Unsupported target for indexed assignment ("object") [index] -apps/job/importers/quote_spreadsheet.py:0: error: "object" has no attribute "update" [attr-defined] -apps/job/importers/quote_spreadsheet.py:0: error: Incompatible types in assignment (expression has type "str", variable has type "ValidationError") [assignment] -apps/job/importers/quote_spreadsheet.py:0: error: Need type annotation for "errors" (hint: "errors: list[] = ...") [var-annotated] -apps/job/importers/quote_spreadsheet.py:0: error: Need type annotation for "warnings" (hint: "warnings: list[] = ...") [var-annotated] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "detect_labour_column" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "detect_material_columns" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Need type annotation for "conflicts" (hint: "conflicts: list[] = ...") [var-annotated] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "_d" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Call to untyped function "find_validation_cells" in typed context [no-untyped-call] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/importers/quote_spreadsheet.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/importers/google_sheets.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Argument 3 to "_upload_to_google_docs" of "Command" has incompatible type "str | None"; expected "str" [arg-type] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Incompatible types in assignment (expression has type "Procedure", variable has type "Form") [assignment] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Need type annotation for "candidates" (hint: "candidates: dict[, ] = ...") [var-annotated] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] -apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "_get_drive_service" in typed context [no-untyped-call] -apps/crm/services/phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -apps/crm/services/phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/services/sales_pipeline_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounting/services/sales_pipeline_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types in assignment (expression has type "float | None", target has type "float") [assignment] -apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types in assignment (expression has type "float | None", target has type "float") [assignment] -apps/accounting/services/sales_pipeline_service.py:0: error: Incompatible types in assignment (expression has type "float | None", target has type "float") [assignment] -apps/accounting/services/sales_pipeline_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Key expression in dictionary comprehension has incompatible type "str | None"; expected type "str" [misc] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/payroll_reconciliation_service.py:0: error: Invalid index type "str | None" for "dict[str, dict[str, Any]]"; expected type "str" [index] -apps/accounting/services/invoice_calculation.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] -apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] -apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] -apps/workflow/services/llm_service.py:0: note: Possible overload variants: -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None -apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str -apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/dev_demo_export_scrubber.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/company/tests/test_get_company_for_xero.py:0: error: Call to untyped function "get_company_for_xero" in typed context [no-untyped-call] -apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value -apps/quoting/mcp.py:0: error: Class cannot subclass "ModelQueryToolset" (has type "Any") [misc] -apps/quoting/mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/mcp.py:0: error: Class cannot subclass "MCPToolset" (has type "Any") [misc] -apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" (default has type "None", parameter has type "str") [assignment] -apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/quoting/mcp.py:0: error: Incompatible default for parameter "dimensions" (default has type "None", parameter has type "str") [assignment] -apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/quoting/mcp.py:0: error: Incompatible default for parameter "labor_hours" (default has type "None", parameter has type "float") [assignment] -apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/quoting/mcp.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/quoting/mcp.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] -apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" (default has type "None", parameter has type "str") [assignment] -apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/quoting/mcp.py:0: error: Need type annotation for "supplier_prices" (hint: "supplier_prices: dict[, ] = ...") [var-annotated] -apps/process/services/form_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/form_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] -apps/operations/services/scheduler_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] -apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Call to untyped function "get_default_cost_set_summary" in typed context [no-untyped-call] -apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/workshop_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/job_profitability_report.py:0: error: Call to untyped function "_get_queryset" in typed context [no-untyped-call] -apps/job/services/job_profitability_report.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/job_profitability_report.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_profitability_report.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/job_profitability_report.py:0: error: Item "float" of "Decimal | float" has no attribute "quantize" [union-attr] -apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | Literal[0]" has no attribute "quantize" [union-attr] -apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | Literal[0]" has no attribute "quantize" [union-attr] -apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | int" has no attribute "quantize" [union-attr] -apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | Literal[0]" has no attribute "quantize" [union-attr] -apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | int" has no attribute "quantize" [union-attr] -apps/job/services/import_quote_service.py:0: error: Unsupported operand types for + ("None" and "int") [operator] -apps/job/services/import_quote_service.py:0: note: Left operand is of type "Any | None" -apps/job/services/import_quote_service.py:0: error: Incompatible types in assignment (expression has type "dict[str, Any | int | None]", target has type "list[dict[str, Any]] | bool | None") [assignment] -apps/job/services/import_quote_service.py:0: error: Incompatible types in assignment (expression has type "dict[str, int | None]", target has type "list[dict[str, Any]] | bool | None") [assignment] -apps/job/services/import_quote_service.py:0: error: Incompatible types in assignment (expression has type "dict[str, int]", target has type "list[dict[str, Any]] | bool | None") [assignment] -apps/job/services/import_quote_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/import_quote_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/import_quote_service.py:0: error: Unsupported operand types for + ("None" and "int") [operator] -apps/job/services/import_quote_service.py:0: note: Left operand is of type "Any | None" -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/google_docs_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/process/services/google_docs_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/services/db_scrubber.py:0: error: Argument 1 to "add" of "set" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/services/data_integrity_service.py:0: error: Dict entry 4 has incompatible type "str": "list[str]"; expected "str": "str" [dict-item] -apps/job/services/data_integrity_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/management/commands/merge_companies.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/services/wip_service.py:0: error: Argument "key" to "sorted" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/accounting/services/wip_service.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value -apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] -apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] -apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] -apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] -apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] -apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] -apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] -apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance -apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] -apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] -apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_search_telemetry.py:0: error: Call to untyped function "result_ids" in typed context [no-untyped-call] -apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_profitability_report_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounting/serializers/rdti_spend_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] -apps/workflow/views/data_versions_view.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/build_id_view.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/reports/pnl.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_draft_jobs_created" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Need type annotation for "jobs_through_quotes" (hint: "jobs_through_quotes: set[] = ...") [var-annotated] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_draft_jobs_created" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_submitted" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_accepted" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_won" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_by_status_path" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_quote_acceptance_rate" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_draft_conversion_rate" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_draft_jobs_created" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_submitted" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_accepted" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_won" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_by_status_path" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_quote_acceptance_rate" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_draft_conversion_rate" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_draft_jobs_created" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_submitted" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_accepted" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_won" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_by_status_path" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_quote_acceptance_rate" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_draft_conversion_rate" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_event_list" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_event_list" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] -apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] -apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "start_date" [union-attr] -apps/accounting/views/sales_forecast_view.py:0: error: Argument 1 to "_get_total_invoiced_for_job" of "SalesForecastMonthDetailAPIView" has incompatible type "Job | None"; expected "Job" [arg-type] -apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "latest_actual" [union-attr] -apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "company" [union-attr] -apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Company | Any | None" has no attribute "name" [union-attr] -apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "job_number" [union-attr] -apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/accounting/views/sales_forecast_view.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/accounting/views/sales_forecast_view.py:0: error: Argument "row_date" to "build_row" has incompatible type "Any | None"; expected "str" [arg-type] -apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] -apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] -apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounts/utils.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/utils.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value -apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value -apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] -apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] -apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] -apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] -apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] -apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] -apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] -apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] -apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value -apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "return_value" [attr-defined] -apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "assert_called_once_with" [attr-defined] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/testing.py:0: note: Use "-> None" if function does not return a value -apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] -apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/timesheet/tests/test_jobs_api_filter.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/tests/test_jobs_api_filter.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/timesheet/tests/test_jobs_api_filter.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_make_special_leave_job" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_book_time" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_make_special_leave_job" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_book_time" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertGreater" of "TestCase" [misc] -apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertGreater" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderGT[Any]" [arg-type] -apps/operations/tests/test_scheduler_service.py:0: error: Incompatible type for lookup 'allocation_date': (got "date | None", expected "str | date") [misc] -apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_set_efficiency" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_set_efficiency" in typed context [no-untyped-call] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertGreater" of "TestCase" [misc] -apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertGreater" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderGT[Any]" [arg-type] -apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertLessEqual" of "TestCase" [misc] -apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertLessEqual" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderLE[Any]" [arg-type] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] -apps/operations/tests/test_scheduler_persistence.py:0: error: Item "None" of "SchedulerRun | None" has no attribute "id" [union-attr] -apps/job/tests/test_workshop_timesheet_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_workshop_timesheet_api.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] -apps/job/tests/test_workshop_pdf_service.py:0: error: Argument 1 to "convert_html_to_reportlab" has incompatible type "None"; expected "str" [arg-type] -apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_mcp_tool_integration.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/job/tests/test_mcp_tool_integration.py:0: error: Missing positional argument "query" in call to "search_products" of "QuotingTool" [call-arg] -apps/job/tests/test_job_files_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] -apps/job/tests/test_costline_schema_validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: error: Need type annotation for "data" (hint: "data: dict[, ] = ...") [var-annotated] -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Cannot assign to a method [method-assign] -apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -apps/crm/tests/test_phone_call_service.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "timedelta" [attr-defined] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/crm/tests/test_phone_call_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/tests/test_company_merge_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/company/tests/test_company_merge_service.py:0: error: Value of type "Any | None" is not indexable [index] -apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_merge_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: "type[SalesPipelineAPITests]" has no attribute "office_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: "SalesPipelineAPITests" has no attribute "office_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounting/tests/test_sales_pipeline_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/tests/test_kanban_search.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] -apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] -apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] -apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/serializers.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] -apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Field" defined the type as "dict[str, str | _StrPromise]") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "BooleanField", base class "Field" defined the type as "bool") [assignment] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "BooleanField", base class "Field" defined the type as "bool") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "SettingsFieldSerializer", base class "Serializer" defined the type as "BindingDict") [assignment] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "JobQuoteChatSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_files_collection_view.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_files_collection_view.py:0: error: Call to untyped function "save_file" in typed context [no-untyped-call] -apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_thumbnail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Returning Any from function declared to return "float" [no-any-return] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Incompatible types in assignment (expression has type "SerializerMethodField", base class "CostSetSerializer" defined the type as "CostLineSerializer") [assignment] -apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_search_alias_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/supplier_pickup_address_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/contact_method_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/company/views/contact_method_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/views/contact_method_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] -apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] -apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_determine_status" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_get_staff_alerts" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] -apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] -apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "int | str | Any" -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "int") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("int" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "CostLine", variable has type "CostLine@AnnotatedWith[TypedDict({'is_billable': str})]") [assignment] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: note: Right operand is of type "Decimal | int" -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "Decimal") [operator] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "Decimal") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "str", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Argument 2 to "_get_color" of "KPIService" has incompatible type "Decimal"; expected "float" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "Decimal", target has type "float") [assignment] -apps/accounting/services/core.py:0: error: Argument "key" to "max" has incompatible type "Callable[[dict[str, object]], object]"; expected "Callable[[dict[str, object]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible return value type (got "object", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/accounting/services/core.py:0: error: Argument 1 to "localtime" has incompatible type "object"; expected "datetime | None" [arg-type] -apps/accounting/services/core.py:0: error: Incompatible types in assignment (expression has type "object", variable has type "date") [assignment] -apps/accounting/services/core.py:0: error: Incompatible return value type (got "None", expected "dict[str, Any]") [return-value] -apps/accounting/services/core.py:0: error: Generator has incompatible item type "Decimal"; expected "bool" [misc] -apps/accounting/services/core.py:0: error: "CostLine" has no attribute "is_billable_meta" [attr-defined] -apps/accounting/services/core.py:0: error: Argument 1 to "_calculate_job_breakdown" of "StaffPerformanceService" has incompatible type "list[CostLine]"; expected "QuerySet[Any, Any]" [arg-type] -apps/accounting/services/core.py:0: error: Missing type arguments for generic type "QuerySet" [type-arg] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for + ("str" and "float") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for - ("str" and "float") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for - ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for / ("float" and "str") [operator] -apps/accounting/services/core.py:0: error: Unsupported operand types for / ("str" and "float") [operator] -apps/accounting/services/core.py:0: error: Unsupported left operand type for / ("str") [operator] -apps/accounting/services/core.py:0: note: Both left and right operands are unions -apps/accounting/services/core.py:0: error: Unsupported operand types for > ("str" and "int") [operator] -apps/accounting/services/core.py:0: note: Left operand is of type "float | Any | str" -apps/accounting/tests/test_core_nplusone.py:0: error: Module "django.utils.timezone" does not explicitly export attribute "datetime" [attr-defined] -apps/accounting/tests/test_core_nplusone.py:0: error: Returning Any from function declared to return "Job" [no-any-return] -apps/accounting/tests/test_core_nplusone.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] +apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] +apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] +apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] +apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] +apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] +apps/job/models/job_event.py:0: error: Argument 1 to "_format_ordinal" has incompatible type "Any | None"; expected "int" [arg-type] +apps/job/models/job_event.py:0: error: Argument 1 to "_format_status" has incompatible type "Any | None"; expected "str" [arg-type] +apps/job/models/job_event.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/job/models/job_event.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] +apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/models/job_event.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/models/job_event.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/models/job_event.py:0: error: Unsupported left operand type for < ("None") [operator] +apps/job/models/job_event.py:0: note: Both left and right operands are unions +apps/job/models/job_file.py:0: error: Argument 1 to "get_job_folder_path" has incompatible type "int"; expected "str" [arg-type] +apps/job/models/job_file.py:0: error: Call to untyped function "get_thumbnail_folder" in typed context [no-untyped-call] +apps/job/models/spreadsheet.py:0: error: Item "None" of "Job | None" has no attribute "job_number" [union-attr] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/permissions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/costing_serializer.py:0: error: Incompatible types in assignment (expression has type "SerializerMethodField", base class "CostSetSerializer" defined the type as "CostLineSerializer") [assignment] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/job/serializers/costing_serializer.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/serializers/costing_serializer.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_integrity_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/data_quality_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_file_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_profitability_report_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_profitability_report_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "DictField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Incompatible types in assignment (expression has type "JobQuoteChatSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_quote_chat_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Argument "choices" to "ChoiceField" has incompatible type "Sequence[tuple[Any, Any]] | Sequence[tuple[str, Iterable[tuple[Any, Any]]]] | None"; expected "Sequence[Any]" [arg-type] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] +apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobSummaryDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "BindingDict") [assignment] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "bool | None" [no-any-return] +apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] +apps/job/serializers/kanban_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/job/services/chat_service.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] +apps/job/services/chat_service.py:0: error: Cannot call function of unknown type [operator] apps/job/services/chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] apps/job/services/chat_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/job/services/chat_service.py:0: error: Cannot call function of unknown type [operator] -apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] -apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/services/data_integrity_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/services/data_integrity_service.py:0: error: Dict entry 4 has incompatible type "str": "list[str]"; expected "str": "str" [dict-item] +apps/job/services/delivery_docket_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/services/delta_checksum.py:0: error: Argument 1 to "join" of "str" has incompatible type "Decimal"; expected "Iterable[str]" [arg-type] +apps/job/services/delta_checksum.py:0: error: Incompatible types in assignment (expression has type "list[str]", variable has type "Decimal") [assignment] +apps/job/services/file_service.py:0: error: Call to untyped function "create_thumbnail" in typed context [no-untyped-call] +apps/job/services/file_service.py:0: error: Call to untyped function "get_thumbnail_folder" in typed context [no-untyped-call] +apps/job/services/file_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/file_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/file_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/file_service.py:0: error: Incompatible types in assignment (expression has type "Image", variable has type "ImageFile") [assignment] +apps/job/services/import_quote_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/import_quote_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/import_quote_service.py:0: error: Incompatible types in assignment (expression has type "dict[str, Any | int | None]", target has type "list[dict[str, Any]] | bool | None") [assignment] +apps/job/services/import_quote_service.py:0: error: Incompatible types in assignment (expression has type "dict[str, int | None]", target has type "list[dict[str, Any]] | bool | None") [assignment] +apps/job/services/import_quote_service.py:0: error: Incompatible types in assignment (expression has type "dict[str, int]", target has type "list[dict[str, Any]] | bool | None") [assignment] +apps/job/services/import_quote_service.py:0: error: Unsupported operand types for + ("None" and "int") [operator] +apps/job/services/import_quote_service.py:0: error: Unsupported operand types for + ("None" and "int") [operator] +apps/job/services/import_quote_service.py:0: note: Left operand is of type "Any | None" +apps/job/services/import_quote_service.py:0: note: Left operand is of type "Any | None" +apps/job/services/job_profitability_report.py:0: error: Call to untyped function "_get_queryset" in typed context [no-untyped-call] +apps/job/services/job_profitability_report.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/job_profitability_report.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_profitability_report.py:0: error: Item "float" of "Decimal | float" has no attribute "quantize" [union-attr] +apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | Literal[0]" has no attribute "quantize" [union-attr] +apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | Literal[0]" has no attribute "quantize" [union-attr] +apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | Literal[0]" has no attribute "quantize" [union-attr] +apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | int" has no attribute "quantize" [union-attr] +apps/job/services/job_profitability_report.py:0: error: Item "int" of "Decimal | int" has no attribute "quantize" [union-attr] +apps/job/services/job_profitability_report.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] +apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] +apps/job/services/job_rest_service.py:0: error: Argument "key" to "sort" of "list" has incompatible type "Callable[[dict[str, int | datetime | UUID | str | Any | None]], int | datetime | UUID | str | Any | None]"; expected "Callable[[dict[str, int | datetime | UUID | str | Any | None]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] +apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] +apps/job/services/job_rest_service.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/job_rest_service.py:0: error: Incompatible default for parameter "week" (default has type "None", parameter has type "date") [assignment] +apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] +apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "int | datetime | UUID | str | Any | None", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] +apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] +apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] +apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/services/job_service.py:0: error: Call to untyped function "_touch_job_for_assignment_change" of "JobStaffService" in typed context [no-untyped-call] +apps/job/services/job_service.py:0: error: Call to untyped function "_touch_job_for_assignment_change" of "JobStaffService" in typed context [no-untyped-call] +apps/job/services/job_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/job/services/job_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/job_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/job_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_categorization_service.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/job/services/kanban_categorization_service.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/job/services/kanban_service.py:0: error: Argument 1 to "_rank_kanban_search_candidates" of "KanbanService" has incompatible type "list[Job@AnnotatedWith[TypedDict({'trigram_score': Any})]]"; expected "list[Job]" [arg-type] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/kanban_service.py:0: error: Incompatible types in assignment (expression has type "list[Job]", variable has type "JobQuerySet") [assignment] +apps/job/services/kanban_service.py:0: error: Invalid index type "slice[None, int, None]" for "dict[str, Any]"; expected type "str" [index] +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Returning Any from function declared to return "float" [no-any-return] +apps/job/services/kanban_service.py:0: error: Value of type "list[dict[str, int | str | Any | None]] | int | dict[str, Any] | str | Any | None" is not indexable [index] +apps/job/services/kanban_service.py:0: note: "list" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance +apps/job/services/kanban_service.py:0: note: Consider using "Sequence" instead, which is covariant +apps/job/services/mcp_chat_service.py:0: error: Dict entry 1 has incompatible type "str": "str | None"; expected "str": "str" [dict-item] +apps/job/services/mcp_chat_service.py:0: error: Dict entry 2 has incompatible type "str": "list[dict[str, dict[str, Any | str] | Any | str]]"; expected "str": "str" [dict-item] +apps/job/services/mcp_chat_service.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/job/services/month_end_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/job/services/month_end_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/month_end_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Cannot call function of unknown type [operator] +apps/job/services/quote_mode_controller.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/quote_mode_controller.py:0: error: Incompatible return value type (got "None", expected "str") [return-value] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/services/quote_mode_controller.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/job/services/quote_mode_controller.py:0: note: Use "-> None" if function does not return a value +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "LABOR" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: "" has no attribute "MATERIAL" [attr-defined] +apps/job/services/quote_sync_service.py:0: error: Argument "quantity" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Argument "unit_cost" to "DraftLine" has incompatible type "float | int"; expected "Decimal" [arg-type] +apps/job/services/quote_sync_service.py:0: error: Call to untyped function "_copy_estimate_to_quote_costset" in typed context [no-untyped-call] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/quote_sync_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/time_entry_rates.py:0: error: Incompatible return value type (got "Any | None", expected "XeroPayItem") [return-value] +apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr] +apps/job/services/time_entry_rates.py:0: error: Item "None" of "Any | None" has no attribute "xero_id" [union-attr] +apps/job/services/workshop_pdf_service.py:0: error: Argument 1 to "Table" has incompatible type "list[object]"; expected "Sequence[list[Any] | tuple[Any, ...]]" [arg-type] +apps/job/services/workshop_pdf_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/services/workshop_pdf_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_handover_section" in typed context [no-untyped-call] +apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_handover_section" in typed context [no-untyped-call] +apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_letterhead_banner" in typed context [no-untyped-call] +apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "add_letterhead_banner" in typed context [no-untyped-call] +apps/job/services/workshop_pdf_service.py:0: error: Call to untyped function "wait_until_file_ready" in typed context [no-untyped-call] +apps/job/services/workshop_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/workshop_pdf_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_pdf_service.py:0: error: Incompatible types in assignment (expression has type "list[Table | Flowable]", variable has type "list[Table]") [assignment] +apps/job/services/workshop_pdf_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/workshop_pdf_service.py:0: error: Module "bs4" does not explicitly export attribute "NavigableString" [attr-defined] +apps/job/services/workshop_pdf_service.py:0: error: Need type annotation for "staff_hours" [var-annotated] +apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "_format_time" of "WorkshopTimesheetService" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "get_default_cost_set_summary" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/services/workshop_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/tasks.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/tasks.py:0: error: Call to untyped function "create_thumbnail" in typed context [no-untyped-call] +apps/job/tasks.py:0: error: Call to untyped function "get_thumbnail_folder" in typed context [no-untyped-call] +apps/job/tests/_pdf_golden_fixtures.py:0: error: Incompatible types in assignment (expression has type "Company", variable has type "CompanyDefaults") [assignment] +apps/job/tests/_pdf_golden_fixtures.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_api_endpoints.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_chat_api_endpoints.py:0: error: Need type annotation for "data" (hint: "data: dict[, ] = ...") [var-annotated] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/tests/test_chat_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/management/commands/test_gemini_chat.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] -apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" -apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/services/purchasing_rest_service.py:0: error: Need type annotation for "updated_line_ids" (hint: "updated_line_ids: set[] = ...") [var-annotated] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] -apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value -apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/job/mixins.py:0: error: Missing type arguments for generic type "GenericAPIView" [type-arg] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Call to untyped function "get_job_by_number" in typed context [no-untyped-call] -apps/job/mixins.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/mixins.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/kanban_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/tests/test_chat_service.py:0: error: Incompatible default for parameter "tool_call_id" (default has type "None", parameter has type "str") [assignment] +apps/job/tests/test_chat_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/tests/test_chat_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/job/tests/test_chat_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/job/tests/test_costline_schema_validation.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/job/tests/test_costline_schema_validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] +apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_delta_rejection_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] +apps/job/tests/test_job_files_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/tests/test_kanban_reorder_priority.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] +apps/job/tests/test_kanban_search.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] +apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] +apps/job/tests/test_mcp_tool_integration.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/job/tests/test_mcp_tool_integration.py:0: error: Missing positional argument "query" in call to "search_products" of "QuotingTool" [call-arg] +apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] +apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_quote_modes.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/tests/test_workshop_pdf_service.py:0: error: Argument 1 to "convert_html_to_reportlab" has incompatible type "None"; expected "str" [arg-type] +apps/job/tests/test_workshop_timesheet_api.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/job/tests/test_workshop_timesheet_api.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] +apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] +apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/archive_completed_jobs_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/assign_job_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] +apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_staff_from_job" of "JobStaffService" in typed context [no-untyped-call] +apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/data_integrity_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/data_quality_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/delivery_docket_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Call to untyped function "_archive_quote_data" in typed context [no-untyped-call] +apps/job/views/job_costing_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/job/views/job_costline_views.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_detail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_file_thumbnail_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] +apps/job/views/job_files_collection_view.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/job/views/job_files_collection_view.py:0: error: Call to untyped function "save_file" in typed context [no-untyped-call] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_files_collection_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_profitability_report_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: "JobQuoteChatSerializer" has no attribute "get" [attr-defined] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: "type[Job]" has no attribute "STATUS_CHOICES" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Argument 1 to "get_weekly_metrics" of "JobRestService" has incompatible type "date | None"; expected "date" [arg-type] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/job/views/job_rest_views.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/job/views/kanban_view_api.py:0: error: "str" has no attribute "HTTP_500_INTERNAL_SERVER_ERROR" [attr-defined] +apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/kanban_view_api.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment] +apps/job/views/modern_timesheet_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "calculated_total_cost" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "id" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "meta" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "quantity" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "unit_cost" [union-attr] +apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostSet | None" has no attribute "rev" [union-attr] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_import_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] +apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/job/views/workshop_pdf_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/views/workshop_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/job/views/workshop_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/job/views/workshop_view.py:0: error: Incompatible type for lookup 'people__id': (got "UUID | None", expected "UUID | str") [misc] +apps/job/views/workshop_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/job/views/workshop_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/serializers/workshop_schedule_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/operations/services/scheduler_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Invalid index type "UUID" for "dict[int, float]"; expected type "int" [index] +apps/operations/services/scheduler_service.py:0: error: Missing type arguments for generic type "frozenset" [type-arg] +apps/operations/tests/test_scheduler_persistence.py:0: error: Item "None" of "SchedulerRun | None" has no attribute "id" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertGreater" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderGT[Any]" [arg-type] +apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertGreater" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderGT[Any]" [arg-type] +apps/operations/tests/test_scheduler_service.py:0: error: Argument 1 to "assertLessEqual" of "TestCase" has incompatible type "date | None"; expected "SupportsDunderLE[Any]" [arg-type] +apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_book_time" in typed context [no-untyped-call] +apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_book_time" in typed context [no-untyped-call] +apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_make_special_leave_job" in typed context [no-untyped-call] +apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_make_special_leave_job" in typed context [no-untyped-call] +apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_set_efficiency" in typed context [no-untyped-call] +apps/operations/tests/test_scheduler_service.py:0: error: Call to untyped function "_set_efficiency" in typed context [no-untyped-call] +apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertGreater" of "TestCase" [misc] +apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertGreater" of "TestCase" [misc] +apps/operations/tests/test_scheduler_service.py:0: error: Cannot infer value of type parameter "_T" of "assertLessEqual" of "TestCase" [misc] +apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/operations/tests/test_scheduler_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/operations/tests/test_scheduler_service.py:0: error: Incompatible type for lookup 'allocation_date': (got "date | None", expected "str | date") [misc] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/tests/test_scheduler_service.py:0: error: Item "None" of "AllocationBlock | None" has no attribute "allocation_date" [union-attr] +apps/operations/views/workshop_schedule_view.py:0: error: Incompatible types in assignment (expression has type "list[JobProjection]", variable has type "QuerySet[JobProjection, JobProjection]") [assignment] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Argument 3 to "_upload_to_google_docs" of "Command" has incompatible type "str | None"; expected "str" [arg-type] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "_get_drive_service" in typed context [no-untyped-call] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Call to untyped function "from_service_account_file" of "Credentials" in typed context [no-untyped-call] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Incompatible types in assignment (expression has type "Procedure", variable has type "Form") [assignment] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/process/management/commands/import_dropbox_hs_documents.py:0: error: Need type annotation for "candidates" (hint: "candidates: dict[, ] = ...") [var-annotated] +apps/process/serializers/form_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/serializers/procedure_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/services/form_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/process/services/form_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/google_docs_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/process/services/google_docs_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/process/services/google_docs_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/procedure_service.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/services/procedure_service.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/services/procedure_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/procedure_service.py:0: note: Use "-> None" if function does not return a value +apps/process/services/safety_ai_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Incompatible return value type (got "dict[Any, Any] | str", expected "dict[str, Any]") [return-value] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "get" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Item "str" of "dict[Any, Any] | str" has no attribute "setdefault" [union-attr] +apps/process/services/safety_ai_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[dict[str, str]]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "list[str]" [no-any-return] +apps/process/services/safety_ai_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/process/services/safety_ai_service.py:0: note: Use "-> None" if function does not return a value +apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/conftest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_model.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_form_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/tests/test_procedure_model.py:0: error: Item "None" of "Procedure | None" has no attribute "title" [union-attr] +apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "assert_called_once_with" [attr-defined] +apps/process/tests/test_procedure_service.py:0: error: "Callable[[str, str], GoogleDocResult]" has no attribute "return_value" [attr-defined] +apps/process/tests/test_procedure_service.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Argument "document_type" to "create_blank_procedure" of "ProcedureService" has incompatible type "Sequence[str]"; expected "str" [arg-type] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "update" of "ProcedureViewSet" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Argument "document_type" to "create_blank_procedure" of "ProcedureService" has incompatible type "Sequence[str]"; expected "str" [arg-type] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "update" of "ProcedureViewSet" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "_get_procedure" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "GoogleDocsService" in typed context [no-untyped-call] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "ProcedureService" in typed context [no-untyped-call] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/process/views/procedure_viewsets.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/procedure_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/procedure_viewsets.py:0: error: Call to untyped function "SafetyAIService" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_category_filter" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "_apply_common_filters" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Argument "document_type" to "create_form" of "FormService" has incompatible type "Sequence[str]"; expected "str" [arg-type] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "update" of "FormViewSet" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Call to untyped function "get_form" in typed context [no-untyped-call] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/views/form_viewsets.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/quote_sync_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[Any, Any]]") [return-value] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobSummaryDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "JobDataSerializer", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "bool | None" [no-any-return] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Argument "choices" to "ChoiceField" has incompatible type "Sequence[tuple[Any, Any]] | Sequence[tuple[str, Iterable[tuple[Any, Any]]]] | None"; expected "Sequence[Any]" [arg-type] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "BindingDict") [assignment] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/serializers/job_serializer.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/job/views/workshop_pdf_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/month_end_rest_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "id" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "meta" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "quantity" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "unit_cost" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostLine@AnnotatedWith[TypedDict({'calculated_total_cost': Any, 'calculated_total_rev': Any})] | None" has no attribute "calculated_total_cost" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Item "None" of "CostSet | None" has no attribute "rev" [union-attr] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/modern_timesheet_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/delivery_docket_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "get_paid_complete_jobs" in typed context [no-untyped-call] -apps/job/views/archive_completed_jobs_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/archive_completed_jobs_view.py:0: error: Call to untyped function "archive_complete_jobs" in typed context [no-untyped-call] -apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/process/views/procedure_viewsets.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/purchasing/models.py:0: error: "PurchaseOrderLine" has no attribute "received_lines" [attr-defined] +apps/purchasing/models.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/models.py:0: error: Call to untyped function "generate_po_number" in typed context [no-untyped-call] +apps/purchasing/models.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] +apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1867,9 +1272,7 @@ apps/purchasing/serializers.py:0: error: Missing type arguments for generic type apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Argument "default" to "DecimalField" has incompatible type "int"; expected "Decimal | Callable[[], Decimal] | _Empty | None" [arg-type] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1879,7 +1282,6 @@ apps/purchasing/serializers.py:0: error: Missing type arguments for generic type apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] @@ -1899,72 +1301,82 @@ apps/purchasing/serializers.py:0: error: Missing type arguments for generic type apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] apps/purchasing/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] +apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/allocation_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/allocation_service.py:0: error: Function "builtins.any" is not valid as a type [valid-type] +apps/purchasing/services/allocation_service.py:0: error: Incompatible return value type (got "tuple[PurchaseOrderLine | None, Stock]", expected "tuple[PurchaseOrderLine, Stock | CostLine]") [return-value] +apps/purchasing/services/allocation_service.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/purchasing/services/allocation_service.py:0: note: Perhaps you meant "typing.Any" instead of "any"? +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/delivery_receipt_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Incompatible type for "unit_cost" of "Stock" (got "Decimal | None", expected "str | float | Decimal | Combinable") [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unexpected attribute "retail_rate" for model "Stock" [misc] +apps/purchasing/services/delivery_receipt_service.py:0: error: Unsupported operand types for * ("None" and "Decimal") [operator] +apps/purchasing/services/delivery_receipt_service.py:0: note: Left operand is of type "Decimal | None" +apps/purchasing/services/purchase_order_email_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "PurchaseOrderPDFGenerator" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_header_info" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_line_items_table" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_logo" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "add_supplier_info" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Call to untyped function "generate" in typed context [no-untyped-call] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: List item 0 has incompatible type "Paragraph"; expected "str" [list-item] +apps/purchasing/services/purchase_order_pdf_service.py:0: error: List item 1 has incompatible type "Paragraph"; expected "str" [list-item] +apps/purchasing/services/purchasing_rest_service.py:0: error: Argument 2 to "_create_line" of "PurchasingRestService" has incompatible type "Any | None"; expected "str" [arg-type] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Call to untyped function (unknown) in typed context [no-untyped-call] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/services/purchasing_rest_service.py:0: error: Incompatible return value type (got "QuerySet[Stock, Stock]", expected "list[dict[str, Any]]") [return-value] +apps/purchasing/services/purchasing_rest_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/purchasing/services/purchasing_rest_service.py:0: error: Need type annotation for "updated_line_ids" (hint: "updated_line_ids: set[] = ...") [var-annotated] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument "contents" to "generate_content" of "Models" has incompatible type "list[dict[str, str]]"; expected "Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict] | list[Content | ContentDict | str | Image | File | FileDict | Part | PartDict | list[str | Image | File | FileDict | Part | PartDict]]" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "clean_json_response" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/purchasing/services/quote_to_po_service.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Dict entry 0 has incompatible type "str": "dict[str, str]"; expected "str": "str" [dict-item] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/services/quote_to_po_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] apps/purchasing/services/stock_search_service.py:0: error: Argument 1 to "add" of "set" has incompatible type "tuple[float, ...]"; expected "tuple[float, float]" [arg-type] apps/purchasing/services/stock_search_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/purchasing/services/stock_search_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/purchasing/services/stock_search_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] apps/purchasing/services/stock_search_service.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Stock, Stock]", variable has type "list[Stock]") [assignment] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Dict entry 0 has incompatible type "str": "str | _StrPromise"; expected "str": "str" [dict-item] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "delete" in typed context [no-untyped-call] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costline_views.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_none_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Need type annotation for "allocations_by_line" (hint: "allocations_by_line: dict[, ] = ...") [var-annotated] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "PurchaseOrderLine | None" has no attribute "id" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] -apps/purchasing/views/purchasing_rest_views.py:0: error: Generator has incompatible item type "int"; expected "bool" [misc] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "create_purchase_order_pdf" in typed context [no-untyped-call] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/services/stock_service.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/tests/test_serializers.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -1997,164 +1409,578 @@ apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a t apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] apps/purchasing/tests/test_stock_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "_hydrate_company_search_results" of "CompanyRestService" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Value of type "list[dict[str, Any]] | int | Any | str | None" is not indexable [index] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/services/company_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/services/company_rest_service.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/company/views/company_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_by_id" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "update_company" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/views/company_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/views/company_rest_views.py:0: error: Incompatible types in assignment (expression has type "CompanyDuplicateErrorResponseSerializer", variable has type "CompanyErrorResponseSerializer") [assignment] -apps/company/views/company_rest_views.py:0: error: Argument 1 to "get_company_jobs" of "CompanyRestService" has incompatible type "str"; expected "UUID" [arg-type] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_fts_search.py:0: error: Incompatible types in assignment (expression has type "None", variable has type "Staff | AnonymousUser") [assignment] -apps/company/tests/test_company_fts_search.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/company/tests/test_company_invoice_summary.py:0: error: Call to untyped function "date_to_datetime" in typed context [no-untyped-call] -apps/accounting/views/kpi_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/accounting/tests/test_sales_pipeline_service.py:0: error: "SalesPipelineServiceFixturesMixin" has no attribute "test_staff" [attr-defined] -apps/workflow/api/xero/auth.py:0: error: Call to untyped function "RateLimitedRESTClient" in typed context [no-untyped-call] -apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "dict[str, Any] | None" [no-any-return] -apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "str" [no-any-return] -apps/workflow/api/xero/active_app.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "get_or_fetch_company" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_log_invoice_sync_events" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "recalculate_job_invoicing_state" has incompatible type "UUID"; expected "str" [arg-type] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "po_number" of "PurchaseOrder" (got "Any | None", expected "str | int | Combinable") [misc] -apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "order_date" of "PurchaseOrder" (got "Any | None", expected "str | date | Combinable") [misc] -apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] -apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] -apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Incompatible type for lookup 'xero_id': (got "Any | None", expected "UUID | str") [misc] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/xero/stock_sync.py:0: error: Missing type arguments for generic type "list" [type-arg] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "Stock") [assignment] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/stock_sync.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Call to untyped function "get_or_fetch_company" in typed context [no-untyped-call] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Call to untyped function "sync_time_entries_bulk" in typed context [no-untyped-call] -apps/workflow/api/xero/push.py:0: error: Call to untyped function "sync_expense_entries_bulk" in typed context [no-untyped-call] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/tests/test_supplier_search.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/views/purchasing_rest_views.py:0: error: "PurchaseOrder" has no attribute "detail_lines" [attr-defined] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_get_if_none_match" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "_precondition_required_response" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "create_purchase_order_pdf" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "get_stock_holding_job" of "Stock" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Call to untyped function "update_xero_status" in typed context [no-untyped-call] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/purchasing/views/purchasing_rest_views.py:0: error: Generator has incompatible item type "int"; expected "bool" [misc] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "Job | None" has no attribute "name" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Item "None" of "PurchaseOrderLine | None" has no attribute "id" [union-attr] +apps/purchasing/views/purchasing_rest_views.py:0: error: Need type annotation for "allocations_by_line" (hint: "allocations_by_line: dict[, ] = ...") [var-annotated] +apps/purchasing/views/stock_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/purchasing/views/supplier_search_rest_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/quoting/management/commands/run_scrapers.py:0: error: Argument 5 to "run_scraper" of "Command" has incompatible type "Any | None"; expected "bool" [arg-type] +apps/quoting/management/commands/run_scrapers.py:0: error: Call to untyped function "get_available_scrapers" in typed context [no-untyped-call] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/management/commands/run_scrapers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/mcp.py:0: error: Class cannot subclass "MCPToolset" (has type "Any") [misc] +apps/quoting/mcp.py:0: error: Class cannot subclass "ModelQueryToolset" (has type "Any") [misc] +apps/quoting/mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/mcp.py:0: error: Incompatible default for parameter "dimensions" (default has type "None", parameter has type "str") [assignment] +apps/quoting/mcp.py:0: error: Incompatible default for parameter "labor_hours" (default has type "None", parameter has type "float") [assignment] +apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" (default has type "None", parameter has type "str") [assignment] +apps/quoting/mcp.py:0: error: Incompatible default for parameter "supplier_name" (default has type "None", parameter has type "str") [assignment] +apps/quoting/mcp.py:0: error: Incompatible types in assignment (expression has type "float", variable has type "int") [assignment] +apps/quoting/mcp.py:0: error: Item "None" of "Company | None" has no attribute "name" [union-attr] +apps/quoting/mcp.py:0: error: Need type annotation for "supplier_prices" (hint: "supplier_prices: dict[, ] = ...") [var-annotated] +apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/quoting/mcp.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/quoting/mcp.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/quoting/scrapers/base.py:0: error: Call to untyped function "cleanup" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "get_product_urls" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "login" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "save_products" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "scrape_product" of "BaseScraper" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Call to untyped function "setup_driver" in typed context [no-untyped-call] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/scrapers/base.py:0: error: Incompatible types in assignment (expression has type "WebDriver", variable has type "None") [assignment] +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/base.py:0: note: Use "-> None" if function does not return a value +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "current_url" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "execute_script" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_element" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "find_elements" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "get" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: "None" has no attribute "page_source" [attr-defined] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], Literal[False] | WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement | bool]"; expected "Callable[[None], object]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Argument 1 to "until" of "WebDriverWait" has incompatible type "Callable[[WebDriver | WebElement], WebElement]"; expected "Callable[[None], Literal[False] | WebElement]" [arg-type] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_all_variants" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_description" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_price_unit" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_specifications" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_text_by_selector" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_direct" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "extract_variants_for_width" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "is_product_url" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Call to untyped function "login" in typed context [no-untyped-call] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/scrapers/steel_and_tube.py:0: error: Value of type variable "D" of "WebDriverWait" cannot be "None" [type-var] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/quoting/services/ai_price_extraction.py:0: error: Call to untyped function "get_prioritized_active_providers" in typed context [no-untyped-call] +apps/quoting/services/ai_price_extraction.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/ai_price_extraction.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "int" [call-overload] +apps/quoting/services/ai_price_extraction.py:0: note: Possible overload variants: +apps/quoting/services/ai_price_extraction.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> int | _T +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> int | None +apps/quoting/services/ai_price_extraction.py:0: note: def get(self, AIProviderTypes, int, /) -> int +apps/quoting/services/pdf_data_validation.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/quoting/services/pdf_import_service.py:0: error: "object" has no attribute "append" [attr-defined] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/services/pdf_import_service.py:0: error: Incompatible return value type (got "None", expected "SupplierProduct") [return-value] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/services/pdf_import_service.py:0: note: Use "-> None" if function does not return a value +apps/quoting/services/providers/common.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/gemini_provider.py:0: error: Argument "config" to "generate_content" of "Models" has incompatible type "dict[str, object]"; expected "GenerateContentConfig | GenerateContentConfigDict | None" [arg-type] +apps/quoting/services/providers/gemini_provider.py:0: error: Call to untyped function "log_token_usage" in typed context [no-untyped-call] +apps/quoting/services/providers/gemini_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "Any | None", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "int", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Incompatible types in assignment (expression has type "list[dict[str, object]]", target has type "Sequence[str]") [assignment] +apps/quoting/services/providers/gemini_provider.py:0: error: Missing type arguments for generic type "List" [type-arg] +apps/quoting/services/providers/gemini_provider.py:0: error: Need type annotation for "supplier_info" (hint: "supplier_info: dict[, ] = ...") [var-annotated] +apps/quoting/services/providers/mistral_provider.py:0: error: Argument 1 to "_parse_price_from_string" of "MistralPriceExtractionProvider" has incompatible type "str | None"; expected "str" [arg-type] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "encode_pdf" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Call to untyped function "ocr_response_to_dict" in typed context [no-untyped-call] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/services/providers/mistral_provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Call to untyped function "_ocr_response" in typed context [no-untyped-call] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests/test_ocr_fixtures.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_mcp.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/tests_utils.py:0: note: Use "-> None" if function does not return a value +apps/quoting/views.py:0: error: Call to untyped function "PDFImportService" in typed context [no-untyped-call] +apps/quoting/views.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/quoting/views_scheduled_tasks.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_create_test_staff" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Call to untyped function "_ensure_test_media_files" in typed context [no-untyped-call] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/testing.py:0: note: Use "-> None" if function does not return a value +apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_leave_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "accounting_date" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | date | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "cost_set" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "CostSet | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "quantity" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible type for "unit_cost" of "CostLine" (got "date | Decimal | CostSet | Staff | str | Any", expected "str | float | Decimal | Combinable") [misc] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "date | Decimal | CostSet | Staff | str | Any", variable has type "Staff") [assignment] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Invalid index type "str | Any | date | Decimal | CostSet | Staff" for "dict[str, int]"; expected type "str" [index] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "CostSet" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Decimal" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "Staff" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "split" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "date" of "str | Any | date | Decimal | CostSet | Staff" has no attribute "startswith" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Item "str" of "date | Decimal | CostSet | Staff | str | Any" has no attribute "isoformat" [union-attr] +apps/timesheet/management/commands/create_overtime_entries.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/create_special_job.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reassign_time_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Argument 4 to "_split_costline" of "Command" has incompatible type "Decimal | CostLine | str | Any"; expected "str" [arg-type] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "_do_preview" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "CostLine") [assignment] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: error: Incompatible types in assignment (expression has type "Decimal | CostLine | str | Any", variable has type "Decimal") [assignment] +apps/timesheet/management/commands/reclassify_overtime_entries.py:0: note: Use "-> None" if function does not return a value +apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/daily_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/modern_timesheet_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/serializers/payroll_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 1 to "_determine_status" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_calculate_percentage" of "DailyTimesheetService" has incompatible type "int"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Argument 2 to "_get_staff_alerts" of "DailyTimesheetService" has incompatible type "Decimal | Literal[0]"; expected "Decimal" [arg-type] +apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] +apps/timesheet/services/daily_timesheet_service.py:0: error: Call to untyped function "ensure_json_serializable" in typed context [no-untyped-call] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/daily_timesheet_service.py:0: error: Missing type arguments for generic type "Dict" [type-arg] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] +apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/timesheet/services/weekly_timesheet_service.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/timesheet/services/weekly_timesheet_service.py:0: error: Need type annotation for "lines_by_staff_day" (hint: "lines_by_staff_day: dict[, ] = ...") [var-annotated] +apps/timesheet/services/xero_hours.py:0: error: Incompatible return value type (got "dict[str | None, Staff]", expected "dict[str, Staff]") [return-value] +apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/timesheet/services/xero_hours.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/timesheet/tests/test_daily_timesheet_service.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/timesheet/tests/test_jobs_api_filter.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/timesheet/tests/test_jobs_api_filter.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/tests/test_jobs_api_filter.py:0: error: Returning Any from function declared to return "Job" [no-any-return] +apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/timesheet/tests/test_payroll_post_api.py:0: error: "_MonkeyPatchedResponse" has no attribute "streaming_content" [attr-defined] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/tests/test_payroll_post_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Call to untyped function "build_timesheet_response" in typed context [no-untyped-call] +apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] +apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/timesheet/views/api.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/workflow/accounting/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/types.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/types.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] +apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] +apps/workflow/accounting/types.py:0: error: Name "date" is not defined [name-defined] +apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.InvoicePayload.date" is not valid as a type [valid-type] +apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.POPayload.date" is not valid as a type [valid-type] +apps/workflow/accounting/types.py:0: error: Variable "apps.workflow.accounting.types.QuotePayload.date" is not valid as a type [valid-type] +apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +apps/workflow/accounting/types.py:0: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/accounting/xero/provider.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] +apps/workflow/accounting/xero/provider.py:0: error: Too many arguments for "get_authentication_url" [call-arg] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_comparison_metrics" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_draft_conversion_rate" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_draft_conversion_rate" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_draft_conversion_rate" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_quote_acceptance_rate" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_quote_acceptance_rate" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "calculate_quote_acceptance_rate" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_draft_jobs_created" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_draft_jobs_created" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_draft_jobs_created" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_draft_jobs_created" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_by_status_path" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_by_status_path" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_by_status_path" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_won" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_won" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_jobs_won" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_accepted" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_accepted" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_accepted" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_submitted" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_submitted" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "get_quotes_submitted" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_event_list" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_event_list" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Call to untyped function "serialize_job_list" in typed context [no-untyped-call] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/job_movement.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/api/reports/job_movement.py:0: error: Need type annotation for "jobs_through_quotes" (hint: "jobs_through_quotes: set[] = ...") [var-annotated] +apps/workflow/api/reports/payroll_reconciliation.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] +apps/workflow/api/reports/pnl.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/reports/utils.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/active_app.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/auth.py:0: error: Call to untyped function "RateLimitedRESTClient" in typed context [no-untyped-call] +apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/auth.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "dict[str, Any] | None" [no-any-return] +apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] +apps/workflow/api/xero/auth.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_handle_rate_limit" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_log_quota" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_log_summary" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_maybe_log_threshold_warning" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_maybe_log_threshold_warning" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_parse_int" of "RateLimitedRESTClient" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_parse_int" of "RateLimitedRESTClient" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_parse_int" of "RateLimitedRESTClient" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_record_quota" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/api/xero/client.py:0: error: Class cannot subclass "RESTClientObject" (has type "Any") [misc] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/client.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Argument "employee_id" to "post_timesheet" has incompatible type "str"; expected "UUID" [arg-type] +apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] +apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] +apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] @@ -2162,36 +1988,94 @@ apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotatio apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] -apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] -apps/workflow/api/xero/payroll.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "date") [assignment] -apps/workflow/api/xero/payroll.py:0: error: Returning Any from function declared to return "date | None" [no-any-return] -apps/workflow/api/xero/payroll.py:0: error: Incompatible default for parameter "payment_date" (default has type "None", parameter has type "date") [assignment] -apps/workflow/api/xero/payroll.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/workflow/api/xero/payroll.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/workflow/api/xero/payroll.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/payroll.py:0: error: Argument "employee_id" to "post_timesheet" has incompatible type "str"; expected "UUID" [arg-type] -apps/workflow/api/xero/payroll.py:0: error: Need type annotation for "leave_ids" (hint: "leave_ids: list[] = ...") [var-annotated] +apps/workflow/api/xero/payroll.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Incompatible default for parameter "payment_date" (default has type "None", parameter has type "date") [assignment] +apps/workflow/api/xero/payroll.py:0: error: Incompatible return value type (got "list[str]", expected "int") [return-value] +apps/workflow/api/xero/payroll.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "date") [assignment] apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "tuple" [type-arg] apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "tuple" [type-arg] apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/payroll.py:0: error: Incompatible return value type (got "list[str]", expected "int") [return-value] apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "List" [type-arg] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/workflow/api/xero/payroll.py:0: error: Missing type arguments for generic type "tuple" [type-arg] +apps/workflow/api/xero/payroll.py:0: error: Need type annotation for "leave_ids" (hint: "leave_ids: list[] = ...") [var-annotated] +apps/workflow/api/xero/payroll.py:0: error: Returning Any from function declared to return "date | None" [no-any-return] +apps/workflow/api/xero/payroll.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True +apps/workflow/api/xero/payroll.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase +apps/workflow/api/xero/push.py:0: error: Call to untyped function "get_or_fetch_company" in typed context [no-untyped-call] +apps/workflow/api/xero/push.py:0: error: Call to untyped function "sync_expense_entries_bulk" in typed context [no-untyped-call] +apps/workflow/api/xero/push.py:0: error: Call to untyped function "sync_time_entries_bulk" in typed context [no-untyped-call] +apps/workflow/api/xero/push.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/push.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Argument after ** must have string keys [arg-type] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_bills" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_credit_notes" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "reprocess_invoices" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/reprocess_xero.py:0: error: Item "None" of "type[InvoiceLineItem] | type[BillLineItem] | type[CreditNoteLineItem] | None" has no attribute "objects" [union-attr] +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/reprocess_xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/api/xero/seed.py:0: error: Argument 1 to "update" of "MutableMapping" has incompatible type "dict[str, str] | dict[str, bool]"; expected "SupportsKeysAndGetItem[str, str]" [arg-type] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "get_all_xero_contacts" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "sync_job_to_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] +apps/workflow/api/xero/seed.py:0: error: Dict entry 0 has incompatible type "str": "int"; expected "str": "str" [dict-item] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/seed.py:0: error: Incompatible types in assignment (expression has type "int", target has type "str") [assignment] +apps/workflow/api/xero/seed.py:0: error: Unsupported operand types for + ("object" and "int") [operator] +apps/workflow/api/xero/seed.py:0: error: Unsupported operand types for + ("object" and "int") [operator] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/stock_sync.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/stock_sync.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/api/xero/stock_sync.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "Stock") [assignment] +apps/workflow/api/xero/stock_sync.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/api/xero/stock_sync.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_last_modified_time" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "update_sync_cursor" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_sync_cursor" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] @@ -2200,553 +2084,669 @@ apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_entities" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "get_sync_cursor" in typed context [no-untyped-call] -apps/workflow/api/xero/sync.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Call to untyped function "sync_local_stock_to_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Call to untyped function "update_sync_cursor" in typed context [no-untyped-call] apps/workflow/api/xero/sync.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "get_all_xero_contacts" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Unsupported operand types for + ("object" and "int") [operator] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "sync_job_to_xero" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Unsupported operand types for + ("object" and "int") [operator] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "transform_pay_run" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/seed.py:0: error: Call to untyped function "_resolve_api_method" in typed context [no-untyped-call] -apps/workflow/api/xero/seed.py:0: error: Dict entry 0 has incompatible type "str": "int"; expected "str": "str" [dict-item] -apps/workflow/api/xero/seed.py:0: error: Argument 1 to "update" of "MutableMapping" has incompatible type "dict[str, str] | dict[str, bool]"; expected "SupportsKeysAndGetItem[str, str]" [arg-type] -apps/workflow/api/xero/seed.py:0: error: Incompatible types in assignment (expression has type "int", target has type "str") [assignment] -apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_quote" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_purchase_order" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] -apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] -apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] -apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/sync.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Any | None"; expected "str" [arg-type] +apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "get" of "dict" has incompatible type "Any | None"; expected "str" [arg-type] +apps/workflow/api/xero/transforms.py:0: error: Argument 1 to "recalculate_job_invoicing_state" has incompatible type "UUID"; expected "str" [arg-type] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "_log_invoice_sync_events" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "clean_json" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "get_or_fetch_company" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "serialize_xero_object" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "set_invoice_or_bill_fields" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Call to untyped function "sync_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "order_date" of "PurchaseOrder" (got "Any | None", expected "str | date | Combinable") [misc] +apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "po_number" of "PurchaseOrder" (got "Any | None", expected "str | int | Combinable") [misc] +apps/workflow/api/xero/transforms.py:0: error: Incompatible type for lookup 'xero_id': (got "Any | None", expected "UUID | str") [misc] +apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] +apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] +apps/workflow/api/xero/transforms.py:0: error: Item "None" of "Any | None" has no attribute "date" [union-attr] +apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/api/xero/transforms.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/authentication.py:0: error: "AbstractBaseUser" has no attribute "is_currently_active" [attr-defined] +apps/workflow/authentication.py:0: error: Call to untyped function "get_raw_token_from_cookie" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/authentication.py:0: error: Call to untyped function "mark_used" in typed context [no-untyped-call] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] -apps/accounts/views/user_profile_view.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/token_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/token_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/accounts/views/token_view.py:0: error: Item "None" of "Any | None" has no attribute "total_seconds" [union-attr] -apps/accounts/views/staff_views.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Missing type arguments for generic type "ListCreateAPIView" [type-arg] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/accounts/views/staff_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/process/urls_rest.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/kanban_view_api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/kanban_view_api.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/kanban_view_api.py:0: error: "str" has no attribute "HTTP_500_INTERNAL_SERVER_ERROR" [attr-defined] -apps/job/views/kanban_view_api.py:0: error: Incompatible types in assignment (expression has type "list[str]", target has type "str") [assignment] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: "JobQuoteChatSerializer" has no attribute "get" [attr-defined] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_message_or_404" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_views.py:0: error: Call to untyped function "get_job_or_404_response" in typed context [no-untyped-call] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_costing_views.py:0: error: Call to untyped function "_archive_quote_data" in typed context [no-untyped-call] -apps/job/views/job_costing_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] -apps/job/views/assign_job_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/assign_job_view.py:0: error: Call to untyped function "remove_staff_from_job" of "JobStaffService" in typed context [no-untyped-call] -apps/job/views/job_quote_chat_api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] -apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/authentication.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/authentication.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/authentication.py:0: error: Returning Any from function declared to return "bool" [no-any-return] +apps/workflow/exception_handlers.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] +apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/management/commands/backfill_kanban_search_telemetry.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run_pipe" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "analyze_fields" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "cannot_be_pii" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "is_uuid_string" in typed context [no-untyped-call] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/backport_data_backup.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] +apps/workflow/management/commands/backport_data_backup.py:0: error: Item "None" of "IO[Any] | None" has no attribute "close" [union-attr] +apps/workflow/management/commands/backport_data_backup.py:0: error: Need type annotation for "field_samples" [var-annotated] +apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/create_service_api_key.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/e2e_cleanup.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_reset_scrub_schema" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_reset_scrub_schema" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run_pipe" in typed context [no-untyped-call] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_batch_create_invoices" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_batch_create_quotes" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_build_invoice_payload" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_build_quote_payload" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_get_invoice_line_unit_amount" of "Command" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_accounts" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_contacts" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_employees" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_invoices" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_projects" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_quotes" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_stock_items" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "seed_companies_to_xero" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "seed_jobs_to_xero" in typed context [no-untyped-call] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/seed_xero_from_database.py:0: error: Item "None" of "str | None" has no attribute "endswith" [union-attr] +apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/sync_sequences.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "_print_create_staff_summary" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "_print_link_staff_summary" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "configure_payroll" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "create_staff" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_employees_simple_dev" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_calendars" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_employees" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_leave_types" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_pay_runs" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_rates" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_tenants" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_tenants" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_users" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Call to untyped function "link_staff" in typed context [no-untyped-call] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value +apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/models/service_api_key.py:0: error: Call to untyped function "generate_api_key" of "ServiceAPIKey" in typed context [no-untyped-call] +apps/workflow/models/service_api_key.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/search_telemetry_serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | None") [assignment] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/search_telemetry_serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/serializers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "BooleanField", base class "Field" defined the type as "bool") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "BooleanField", base class "Field" defined the type as "bool") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "CharField", base class "Field" defined the type as "str | _StrPromise | None") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Field" defined the type as "Mapping[str, Any]") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "JSONField", base class "Serializer" defined the type as "ReturnDict[Any, Any]") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "ListField", base class "Field" defined the type as "dict[str, str | _StrPromise]") [assignment] +apps/workflow/serializers.py:0: error: Incompatible types in assignment (expression has type "SettingsFieldSerializer", base class "Serializer" defined the type as "BindingDict") [assignment] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/serializers.py:0: error: Returning Any from function declared to return "str | None" [no-any-return] +apps/workflow/services/db_scrubber.py:0: error: Argument 1 to "add" of "set" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/services/dev_demo_export_scrubber.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/services/error_persistence.py:0: error: Call to untyped function "_extract_caller_context" in typed context [no-untyped-call] +apps/workflow/services/error_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/error_persistence.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/error_persistence.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/services/error_persistence.py:0: error: Incompatible type for "reference_id" of "XeroError" (got "str | None", expected "str | int | Combinable") [misc] +apps/workflow/services/error_persistence.py:0: error: Item "None" of "FrameType | Any | None" has no attribute "f_back" [union-attr] +apps/workflow/services/error_persistence.py:0: error: Item "None" of "FrameType | Any | None" has no attribute "f_code" [union-attr] +apps/workflow/services/error_persistence.py:0: error: Item "None" of "FrameType | Any | None" has no attribute "f_code" [union-attr] +apps/workflow/services/error_persistence.py:0: error: Item "None" of "FrameType | None" has no attribute "f_back" [union-attr] +apps/workflow/services/llm_service.py:0: error: Call to untyped function "get_default" of "AIProvider" in typed context [no-untyped-call] +apps/workflow/services/llm_service.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/services/llm_service.py:0: error: Module "litellm" does not explicitly export attribute "set_verbose" [attr-defined] +apps/workflow/services/llm_service.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return] +apps/workflow/services/llm_service.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/llm_service.py:0: note: Possible overload variants: +apps/workflow/services/llm_service.py:0: note: def [_T] get(self, AIProviderTypes, _T, /) -> str | _T +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, None = ..., /) -> str | None +apps/workflow/services/llm_service.py:0: note: def get(self, AIProviderTypes, str, /) -> str +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/request.py:0: error: Returning Any from function declared to return "str" [no-any-return] +apps/workflow/services/search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/search_telemetry.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/session_replay_service.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/services/session_replay_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/validation.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/services/validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/validation.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/services/validation.py:0: error: Missing type arguments for generic type "dict" [type-arg] apps/workflow/services/xero_sync_service.py:0: error: "Callable[[str], None]" has no attribute "delay" [attr-defined] +apps/workflow/services/xero_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/services/xero_sync_service.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/services/xero_sync_service.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Too many arguments for "get_authentication_url" [call-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_build_line_items" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_to_xero_payload" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Returning Any from function declared to return "DocumentResult" [no-any-return] -apps/workflow/accounting/xero/provider.py:0: error: Call to untyped function "_make_error_result" of "XeroAccountingProvider" in typed context [no-untyped-call] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/accounting/xero/provider.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/accounting/xero/provider.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] -apps/timesheet/views/api.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Call to untyped function "build_timesheet_response" in typed context [no-untyped-call] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/views/api.py:0: error: Call to untyped function "generate_payroll_events" in typed context [no-untyped-call] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/middleware.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/workflow/extensions.py:0: error: Call to untyped function "__init_subclass__" in typed context [no-untyped-call] -apps/workflow/extensions.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "ReturnDict[Any, Any]", expected "list[dict[str, Any]]") [return-value] -apps/job/services/job_rest_service.py:0: error: "ValueError" has no attribute "delta_rejection_context" [attr-defined] -apps/job/services/job_rest_service.py:0: error: Assignment to variable "exc" outside except: block [misc] -apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] -apps/job/services/job_rest_service.py:0: error: Trying to read deleted variable "exc" [misc] -apps/job/services/job_rest_service.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/services/job_rest_service.py:0: error: Argument "key" to "sort" of "list" has incompatible type "Callable[[dict[str, int | datetime | UUID | str | Any | None]], int | datetime | UUID | str | Any | None]"; expected "Callable[[dict[str, int | datetime | UUID | str | Any | None]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]" [arg-type] -apps/job/services/job_rest_service.py:0: error: Incompatible return value type (got "int | datetime | UUID | str | Any | None", expected "SupportsDunderLT[Any] | SupportsDunderGT[Any]") [return-value] -apps/job/services/job_rest_service.py:0: error: Incompatible default for parameter "week" (default has type "None", parameter has type "date") [assignment] -apps/job/services/job_rest_service.py:0: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True -apps/job/services/job_rest_service.py:0: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase -apps/job/services/job_rest_service.py:0: error: "Job" has no attribute "pricings" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Module "drf_spectacular.utils" does not explicitly export attribute "OpenApiTypes" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Returning Any from function declared to return "dict[str, Any]" [no-any-return] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "get_serializer_class" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Argument 1 to "get_weekly_metrics" of "JobRestService" has incompatible type "date | None"; expected "date" [arg-type] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Call to untyped function "calculate_profit_margin" in typed context [no-untyped-call] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: "type[Job]" has no attribute "STATUS_CHOICES" [attr-defined] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/job_rest_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_job_delta_rejection_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/tests/test_event_deduplication.py:0: error: Call to untyped function "create_safe" of "JobEvent" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "staff" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_after" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Value of type "Any | None" is not indexable [index] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_before" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Argument 2 to "assertIn" of "TestCase" has incompatible type "Any | None"; expected "Iterable[Any] | Container[Any]" [arg-type] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "schema_version" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "change_id" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_meta" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "delta_checksum" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "event_type" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "detail" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Item "None" of "JobEvent | None" has no attribute "description" [union-attr] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "untracked_update" in typed context [no-untyped-call] -apps/job/tests/test_job_event_tracking.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_contact" in typed context [no-untyped-call] apps/workflow/tasks.py:0: error: Call to untyped function "sync_single_invoice" in typed context [no-untyped-call] +apps/workflow/tests/fixtures/xero_responses.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Call to untyped function "_get_all_url_patterns" in typed context [no-untyped-call] +apps/workflow/tests/test_api_schema_coverage.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_app_error_grouped_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_celery_setup.py:0: error: "Callable[[], str]" has no attribute "apply" [attr-defined] apps/workflow/tests/test_celery_setup.py:0: error: "Celery" has no attribute "main" [attr-defined] apps/workflow/tests/test_celery_setup.py:0: error: "Celery" has no attribute "tasks" [attr-defined] -apps/workflow/tests/test_celery_setup.py:0: error: "Callable[[], str]" has no attribute "apply" [attr-defined] apps/workflow/tests/test_celery_setup.py:0: error: "Signal" has no attribute "send" [attr-defined] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] apps/workflow/tests/test_celery_setup.py:0: error: Value of type "Any | None" is not indexable [index] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "assign_staff_to_job" of "JobStaffService" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_data_versions_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_dev_demo_export.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_error_grouping.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/workflow/tests/test_localdate_regression.py:0: error: Call to untyped function "update" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "bulk_create_contacts_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "create_company_contact_in_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Call to untyped function "sync_company_to_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_push_contacts.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_search_telemetry.py:0: error: Call to untyped function "result_ids" in typed context [no-untyped-call] +apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_search_telemetry.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] +apps/workflow/tests/test_seed_xero_from_database.py:0: error: Incompatible types in assignment (expression has type "StringIO", variable has type "OutputWrapper") [assignment] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Argument 1 to "Path" has incompatible type "str | None"; expected "str | PathLike[str]" [arg-type] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_session_replay_api.py:0: error: Value of type "Any | None" is not indexable [index] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "_make_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Call to untyped function "sync_companies" in typed context [no-untyped-call] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_sync_clients.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_tasks.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] +apps/workflow/tests/test_xero_app_active.py:0: error: Value of type "dict[str, Any] | None" is not indexable [index] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Call to untyped function "_FakeProvider" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Cannot assign to a method [method-assign] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "_FakeProvider", variable has type "AccountingProvider") [assignment] +apps/workflow/tests/test_xero_document_raw_json.py:0: error: Incompatible types in assignment (expression has type "def _attach_workshop_pdf(self, external_id: str) -> None", variable has type "def _attach_workshop_pdf(self, invoice_external_id: str) -> str | None") [assignment] +apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_leave.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Call to untyped function "_draft" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_payroll_pay_run_flow.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_po_manager.py:0: error: "XeroPurchaseOrderManagerConstructionTests" has no attribute "purchase_order" [attr-defined] +apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "purchase_order" [attr-defined] +apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "supplier" [attr-defined] +apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "supplier" [attr-defined] +apps/workflow/tests/test_xero_po_manager.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_po_manager.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_gen" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_handle_rate_limit" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.api.xero.stock_sync" does not explicitly export attribute "XeroAccount" [attr-defined] +apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] +apps/workflow/tests/test_xero_setup_command.py:0: error: Cannot assign to a method [method-assign] +apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "_extract_required_fields_xero" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "resolve_company_from_xero_contact" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_purchase_order" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Call to untyped function "transform_quote" in typed context [no-untyped-call] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/tests/test_xero_transform_contact_resolution.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/utils.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/ai_provider_viewset.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] +apps/workflow/views/app_error_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] +apps/workflow/views/build_id_view.py:0: error: Missing type arguments for generic type "list" [type-arg] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_logo_api.py:0: error: Call to untyped function "_remove_if_user_uploaded" in typed context [no-untyped-call] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/company_defaults_logo_api.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/data_versions_view.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Call to untyped function "has_permission" in typed context [no-untyped-call] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/session_replay_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_base_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_helpers.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_helpers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_helpers.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument "client_external_id" to "InvoicePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 1 to "_attach_workshop_pdf" of "XeroInvoiceManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Cannot resolve keyword 'created_at' into field. Choices are: amount_due, billing_metadata, company, company_id, date, django_created_at, django_updated_at, due_date, id, job, job_id, line_items, number, online_url, raw_json, status, tax, total_excl_tax, total_incl_tax, xero_id, xero_last_modified, xero_last_synced, xero_tenant_id [misc] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "paid" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_invoice_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument "supplier_external_id" to "POPayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "Decimal" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str | None" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Argument 1 to "DocumentLineItem" has incompatible type "**dict[str, object]"; expected "str" [arg-type] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "save" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Call to untyped function "validate_for_xero_sync" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_po_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument "client_external_id" to "QuotePayload" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Argument 2 to "_add_xero_history_note" of "XeroDocumentManager" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "get_xero_id" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "state_valid_for_xero" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Call to untyped function "validate_company" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Incompatible type for "xero_id" of "Quote" (got "str | None", expected "str | UUID") [misc] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "id" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quote" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "quoted" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: error: Item "None" of "Job | None" has no attribute "save" [union-attr] +apps/workflow/views/xero/xero_quote_manager.py:0: note: Use "-> None" if function does not return a value +apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument "xero_invoice_id" to "XeroInvoiceManager" has incompatible type "UUID"; expected "str | None" [arg-type] apps/workflow/views/xero/xero_view.py:0: error: Argument 1 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "exchange_code_for_token" has incompatible type "str | None"; expected "str" [arg-type] apps/workflow/views/xero/xero_view.py:0: error: Argument 3 to "exchange_code_for_token" has incompatible type "Any | None"; expected "str" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Returning Any from function declared to return "HttpResponse" [no-any-return] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] +apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "generate_xero_sync_events" in typed context [no-untyped-call] apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_active_task_id" of "XeroSyncService" in typed context [no-untyped-call] apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "get_messages" of "XeroSyncService" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible return value type (got "JsonResponse", expected "StreamingHttpResponse") [return-value] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "generate_xero_sync_events" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentSuccessResponseSerializer", variable has type "XeroDocumentErrorResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument "company" to "XeroInvoiceManager" has incompatible type "Company | None"; expected "Company" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroInvoiceManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "xero_invoice_id" to "XeroInvoiceManager" has incompatible type "UUID"; expected "str | None" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Argument "staff" to "XeroPurchaseOrderManager" has incompatible type "Staff | AnonymousUser"; expected "Staff" [arg-type] -apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] -apps/workflow/views/xero/xero_view.py:0: error: Argument 2 to "error" has incompatible type "object"; expected "str | _StrPromise" [arg-type] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] -apps/workflow/views/xero/xero_view.py:0: error: Call to untyped function "_get_last_sync_time" in typed context [no-untyped-call] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/views/xero/xero_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible return value type (got "JsonResponse", expected "StreamingHttpResponse") [return-value] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentErrorResponseSerializer", variable has type "XeroDocumentSuccessResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Incompatible types in assignment (expression has type "XeroDocumentSuccessResponseSerializer", variable has type "XeroDocumentErrorResponseSerializer") [assignment] apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "ListAPIView" [type-arg] apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "RetrieveAPIView" [type-arg] -apps/workflow/tests/test_xero_po_manager.py:0: error: Call to untyped function "setUpTestData" of "BaseAPITestCase" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "supplier" [attr-defined] -apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "purchase_order" [attr-defined] -apps/workflow/tests/test_xero_po_manager.py:0: error: "type[XeroPurchaseOrderManagerConstructionTests]" has no attribute "supplier" [attr-defined] -apps/workflow/tests/test_xero_po_manager.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_po_manager.py:0: error: "XeroPurchaseOrderManagerConstructionTests" has no attribute "purchase_order" [attr-defined] -apps/workflow/tests/test_xero_app_active.py:0: error: Value of type "dict[str, Any] | None" is not indexable [index] -apps/timesheet/services/payroll_employee_sync.py:0: error: Incompatible return value type (got "str | None", expected "str") [return-value] -apps/timesheet/services/payroll_employee_sync.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/timesheet/services/payroll_employee_sync.py:0: error: Call to untyped function "_hours_between" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_accounts" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_contacts" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_projects" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_employees" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_invoices" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_quotes" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_stock_items" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_xero_data" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "seed_companies_to_xero" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "seed_jobs_to_xero" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_batch_create_invoices" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_get_invoice_line_unit_amount" of "Command" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_build_invoice_payload" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_batch_create_quotes" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "clean_payload" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_build_quote_payload" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Item "None" of "str | None" has no attribute "endswith" [union-attr] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_column_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "_table_exists" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_seed_xero_from_database.py:0: error: Incompatible types in assignment (expression has type "StringIO", variable has type "OutputWrapper") [assignment] -apps/workflow/tests/test_seed_xero_from_database.py:0: error: Call to untyped function "clear_production_xero_ids" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Call to untyped function "draft_line_to_dict" in typed context [no-untyped-call] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] -apps/job/views/quote_sync_views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item] -apps/job/views/quote_sync_views.py:0: error: Incompatible types in assignment (expression has type "ApplyQuoteErrorResponseSerializer", variable has type "QuoteSyncErrorResponseSerializer") [assignment] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Missing type arguments for generic type "dict" [type-arg] +apps/workflow/views/xero/xero_view.py:0: error: Returning Any from function declared to return "HttpResponse" [no-any-return] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a return type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Function is missing a type annotation [no-untyped-def] +apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "ModelViewSet" [type-arg] +apps/workflow/views/xero_apps_view.py:0: error: Missing type arguments for generic type "Serializer" [type-arg] +apps/workflow/views/xero_pay_item_viewset.py:0: error: Missing type arguments for generic type "ReadOnlyModelViewSet" [type-arg] apps/workflow/xero_webhooks.py:0: error: "Callable[[str, dict[str, Any]], None]" has no attribute "delay" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_handle_rate_limit" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_store_quota_snapshot" in typed context [no-untyped-call] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.api.xero.stock_sync" does not explicitly export attribute "XeroAccount" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/tests/test_xero_quota_floor.py:0: error: Call to untyped function "_gen" in typed context [no-untyped-call] -apps/workflow/tests/test_tasks.py:0: error: Module "apps.workflow.tasks" does not explicitly export attribute "xero_sync_task" [attr-defined] -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_users" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_employees" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_rates" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_calendars" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_leave_types" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_payroll_pay_runs" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "configure_payroll" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "link_staff" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "create_staff" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_tenants" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_tenants" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "get_employees_simple_dev" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: note: Use "-> None" if function does not return a value -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "_print_link_staff_summary" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Call to untyped function "_print_create_staff_summary" in typed context [no-untyped-call] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/xero.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a return type annotation [no-untyped-def] -apps/timesheet/api/daily_timesheet_views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/tests/test_xero_setup_command.py:0: error: Cannot assign to a method [method-assign] -apps/workflow/apps.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] -apps/workflow/apps.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/accounts/tests/test_auth_observability.py:0: error: Call to untyped function "authenticate" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_reset_scrub_schema" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run_pipe" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_reset_scrub_schema" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/export_dev_demo_dump.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "analyze_fields" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "str") [assignment] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run_pipe" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "_run" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Item "None" of "IO[Any] | None" has no attribute "close" [union-attr] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Need type annotation for "field_samples" [var-annotated] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "cannot_be_pii" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "is_uuid_string" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] -apps/workflow/management/commands/backport_data_backup.py:0: error: Call to untyped function "collect_field_samples" in typed context [no-untyped-call] +docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_postrun" [attr-defined] +docketworks/celery.py:0: error: Module "celery.signals" has no attribute "task_prerun" [attr-defined] +docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_setup" untyped [untyped-decorator] +docketworks/celery.py:0: error: Untyped decorator makes function "_nplusone_teardown" untyped [untyped-decorator] +docketworks/settings.py:0: error: Argument 1 to "int" has incompatible type "str | None"; expected "str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "int" has incompatible type "str | None"; expected "str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "int" has incompatible type "str | None"; expected "str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "int" has incompatible type "str | None"; expected "str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Argument 1 to "join" has incompatible type "str | None"; expected "str" [arg-type] +docketworks/settings.py:0: error: Call to untyped function "configure_site_for_environment" in typed context [no-untyped-call] +docketworks/settings.py:0: error: Function is missing a return type annotation [no-untyped-def] +docketworks/settings.py:0: error: Function is missing a type annotation [no-untyped-def] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "lower" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "rstrip" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "split" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "split" [union-attr] +docketworks/settings.py:0: error: Item "None" of "str | None" has no attribute "split" [union-attr] +docketworks/settings.py:0: note: Use "-> None" if function does not return a value diff --git a/scripts/check_mypy.sh b/scripts/check_mypy.sh index 8d7341e3e..b535b47e4 100755 --- a/scripts/check_mypy.sh +++ b/scripts/check_mypy.sh @@ -2,7 +2,9 @@ # Authoritative backend type check (KAN-205). # Runs full-strict mypy and fails on any error not recorded in mypy-baseline.txt. # After fixing baselined errors, shrink the baseline with: -# poetry run mypy apps/ docketworks/ | poetry run mypy-baseline sync +# poetry run mypy apps/ docketworks/ | poetry run mypy-baseline sync --sort-baseline +# --sort-baseline keeps the file in canonical order so diffs show only real +# add/remove, not mypy's output-order reshuffling. # # mypy exits 1 whenever the (baselined) errors exist, so its exit code is not # the gate — mypy-baseline filter's is. We still guard against mypy crashing From 537055b07c94fa4690fb569f49d62820b5a02aa6 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 15:57:03 +1200 Subject: [PATCH 28/39] fix: render unset phone credentials as null --- .../tests/test_xero_instance_templates.py | 60 +++++++++++++++++-- scripts/server/instance.sh | 20 ++++--- .../phone-provider-settings.json.template | 6 +- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/apps/workflow/tests/test_xero_instance_templates.py b/apps/workflow/tests/test_xero_instance_templates.py index 24e14c20c..d5a5f1e3c 100644 --- a/apps/workflow/tests/test_xero_instance_templates.py +++ b/apps/workflow/tests/test_xero_instance_templates.py @@ -1,4 +1,5 @@ import json +import os import subprocess import tempfile from decimal import Decimal @@ -10,11 +11,12 @@ from django.test import SimpleTestCase, TestCase from apps.accounts.models import Staff -from apps.crm.models import PhoneEndpoint +from apps.crm.models import PhoneEndpoint, PhoneProviderSettings from apps.workflow.models import CompanyDefaults, XeroApp REPO_ROOT = Path(__file__).resolve().parents[3] COMMON_SCRIPT = REPO_ROOT / "scripts" / "server" / "common.sh" +INSTANCE_SCRIPT = REPO_ROOT / "scripts" / "server" / "instance.sh" XERO_APPS_TEMPLATE = ( REPO_ROOT / "scripts" / "server" / "templates" / "xero-apps.json.template" ) @@ -135,9 +137,9 @@ def test_phone_provider_settings_template_renders_to_valid_json(self) -> None: "__PHONE_PROVIDER_BASE_URL_JSON__", '"http://phone-provider.lan"', ) - .replace("__PHONE_PROVIDER_USERNAME__", "phone-user") - .replace("__PHONE_PROVIDER_PASSWORD__", "phone-secret") - .replace("__PHONE_PROVIDER_ACCOUNT_CODE__", "15539090") + .replace("__PHONE_PROVIDER_USERNAME_JSON__", '"phone-user"') + .replace("__PHONE_PROVIDER_PASSWORD_JSON__", '"phone-secret"') + .replace("__PHONE_PROVIDER_ACCOUNT_CODE_JSON__", '"15539090"') ) payload = json.loads(rendered) @@ -237,3 +239,53 @@ def run(creds_file: str) -> "subprocess.CompletedProcess[str]": link = base / "linkdir" link.symlink_to(base) self.assertNotEqual(run(str(link / "inst.credentials.env")).returncode, 0) + + +class PhoneProviderReconfigureFixtureTests(TestCase): + def test_unconfigured_fixture_loads_with_null_credentials(self) -> None: + """Reconfigure must seed a scrubbed instance without violating constraints.""" + PhoneProviderSettings.objects.all().delete() + PhoneProviderSettings.get_solo() + + with tempfile.TemporaryDirectory() as instance_dir: + environment = os.environ.copy() + for variable in ( + "PHONE_PROVIDER_BASE_URL", + "PHONE_PROVIDER_USERNAME", + "PHONE_PROVIDER_PASSWORD", + "PHONE_PROVIDER_ACCOUNT_CODE", + "PHONE_PROVIDER_DOWNLOADS_ENABLED", + "PHONE_PROVIDER_RECORDING_DELETION_ENABLED", + ): + environment.pop(variable, None) + + subprocess.run( + [ + "bash", + "-c", + ( + 'source "$1"; ' + "log() { :; }; " + "chown() { :; }; " + 'render_phone_provider_settings_fixture "$2" ignored' + ), + str(INSTANCE_SCRIPT.parent / "test-harness"), + str(INSTANCE_SCRIPT), + instance_dir, + ], + check=True, + capture_output=True, + text=True, + env=environment, + ) + + fixture = Path(instance_dir) / ".fixtures" / "phone_provider_settings.json" + call_command("loaddata", str(fixture), verbosity=0) + + settings = PhoneProviderSettings.objects.get(pk=1) + self.assertFalse(settings.downloads_enabled) + self.assertFalse(settings.recording_deletion_enabled) + self.assertIsNone(settings.base_url) + self.assertIsNone(settings.username) + self.assertIsNone(settings.password) + self.assertIsNone(settings.account_code) diff --git a/scripts/server/instance.sh b/scripts/server/instance.sh index de52994b0..80b7ed4cb 100755 --- a/scripts/server/instance.sh +++ b/scripts/server/instance.sh @@ -325,19 +325,19 @@ render_phone_provider_settings_fixture() { log "Generating phone provider settings fixture..." mkdir -p "$fixture_dir" - local ESC_PHONE_PROVIDER_USERNAME ESC_PHONE_PROVIDER_PASSWORD ESC_PHONE_PROVIDER_ACCOUNT_CODE - local PHONE_PROVIDER_BASE_URL_JSON - ESC_PHONE_PROVIDER_USERNAME="$(sed_escape "${PHONE_PROVIDER_USERNAME:-}")" - ESC_PHONE_PROVIDER_PASSWORD="$(sed_escape "${PHONE_PROVIDER_PASSWORD:-}")" - ESC_PHONE_PROVIDER_ACCOUNT_CODE="$(sed_escape "${PHONE_PROVIDER_ACCOUNT_CODE:-}")" + local PHONE_PROVIDER_BASE_URL_JSON PHONE_PROVIDER_USERNAME_JSON + local PHONE_PROVIDER_PASSWORD_JSON PHONE_PROVIDER_ACCOUNT_CODE_JSON PHONE_PROVIDER_BASE_URL_JSON="$(sed_escape "$(json_string_or_null "${PHONE_PROVIDER_BASE_URL:-}")")" + PHONE_PROVIDER_USERNAME_JSON="$(sed_escape "$(json_string_or_null "${PHONE_PROVIDER_USERNAME:-}")")" + PHONE_PROVIDER_PASSWORD_JSON="$(sed_escape "$(json_string_or_null "${PHONE_PROVIDER_PASSWORD:-}")")" + PHONE_PROVIDER_ACCOUNT_CODE_JSON="$(sed_escape "$(json_string_or_null "${PHONE_PROVIDER_ACCOUNT_CODE:-}")")" sed \ -e "s|__PHONE_PROVIDER_DOWNLOADS_ENABLED__|${PHONE_PROVIDER_DOWNLOADS_ENABLED:-false}|g" \ -e "s|__PHONE_PROVIDER_RECORDING_DELETION_ENABLED__|${PHONE_PROVIDER_RECORDING_DELETION_ENABLED:-false}|g" \ -e "s|__PHONE_PROVIDER_BASE_URL_JSON__|$PHONE_PROVIDER_BASE_URL_JSON|g" \ - -e "s|__PHONE_PROVIDER_USERNAME__|$ESC_PHONE_PROVIDER_USERNAME|g" \ - -e "s|__PHONE_PROVIDER_PASSWORD__|$ESC_PHONE_PROVIDER_PASSWORD|g" \ - -e "s|__PHONE_PROVIDER_ACCOUNT_CODE__|$ESC_PHONE_PROVIDER_ACCOUNT_CODE|g" \ + -e "s|__PHONE_PROVIDER_USERNAME_JSON__|$PHONE_PROVIDER_USERNAME_JSON|g" \ + -e "s|__PHONE_PROVIDER_PASSWORD_JSON__|$PHONE_PROVIDER_PASSWORD_JSON|g" \ + -e "s|__PHONE_PROVIDER_ACCOUNT_CODE_JSON__|$PHONE_PROVIDER_ACCOUNT_CODE_JSON|g" \ "$TEMPLATE_DIR/phone-provider-settings.json.template" \ > "$fixture_dir/phone_provider_settings.json" chown -R "$instance_user:$instance_user" "$fixture_dir" @@ -1004,6 +1004,10 @@ do_list() { # ============================================================ # main # ============================================================ +if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then + return 0 +fi + if [[ $# -lt 1 ]]; then echo "Usage: $0 {prepare-config|create|reconfigure|destroy|status|list} [args...]" echo " prepare-config [--seed]" diff --git a/scripts/server/templates/phone-provider-settings.json.template b/scripts/server/templates/phone-provider-settings.json.template index ccb6fdc54..99b5c8017 100644 --- a/scripts/server/templates/phone-provider-settings.json.template +++ b/scripts/server/templates/phone-provider-settings.json.template @@ -6,9 +6,9 @@ "downloads_enabled": __PHONE_PROVIDER_DOWNLOADS_ENABLED__, "recording_deletion_enabled": __PHONE_PROVIDER_RECORDING_DELETION_ENABLED__, "base_url": __PHONE_PROVIDER_BASE_URL_JSON__, - "username": "__PHONE_PROVIDER_USERNAME__", - "password": "__PHONE_PROVIDER_PASSWORD__", - "account_code": "__PHONE_PROVIDER_ACCOUNT_CODE__", + "username": __PHONE_PROVIDER_USERNAME_JSON__, + "password": __PHONE_PROVIDER_PASSWORD_JSON__, + "account_code": __PHONE_PROVIDER_ACCOUNT_CODE_JSON__, "created_at": "2024-01-01T00:00:00Z", "updated_at": "2024-01-01T00:00:00Z" } From 6f9995cd416319dff4e01d0b44e2e395dd781bfa Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 16:04:04 +1200 Subject: [PATCH 29/39] fix: normalise empty Xero account fields --- apps/workflow/api/xero/transforms.py | 12 +-- .../commands/seed_xero_from_database.py | 10 +-- .../tests/test_seed_xero_from_database.py | 84 ++++++++++++++++++- mypy-baseline.txt | 3 - 4 files changed, 95 insertions(+), 14 deletions(-) diff --git a/apps/workflow/api/xero/transforms.py b/apps/workflow/api/xero/transforms.py index 4d12e43cb..9bb49d18c 100644 --- a/apps/workflow/api/xero/transforms.py +++ b/apps/workflow/api/xero/transforms.py @@ -1,5 +1,6 @@ import logging import time +from collections.abc import Iterable from datetime import date, datetime from datetime import timezone as dt_timezone from decimal import Decimal @@ -7,6 +8,7 @@ from django.utils import timezone from xero_python.accounting import AccountingApi +from xero_python.accounting.models import Account from apps.accounting.models import Bill, CreditNote, Invoice, Quote from apps.company.models import Company @@ -999,17 +1001,17 @@ def sync_companies(xero_contacts): return companies -def sync_accounts(xero_accounts): +def sync_accounts(xero_accounts: Iterable[Account]) -> None: """Sync Xero accounts""" for account in xero_accounts: XeroAccount.objects.update_or_create( xero_id=account.account_id, defaults={ - "account_code": account.code, + "account_code": account.code or None, "account_name": account.name, - "description": getattr(account, "description", None), - "account_type": account.type, - "tax_type": account.tax_type, + "description": getattr(account, "description", None) or None, + "account_type": account.type or None, + "tax_type": account.tax_type or None, "enable_payments": getattr( account, "enable_payments_to_account", False ), diff --git a/apps/workflow/management/commands/seed_xero_from_database.py b/apps/workflow/management/commands/seed_xero_from_database.py index a21b39ac5..b3a2a52fa 100644 --- a/apps/workflow/management/commands/seed_xero_from_database.py +++ b/apps/workflow/management/commands/seed_xero_from_database.py @@ -178,7 +178,7 @@ def handle(self, *args, **options): CompanyDefaults.set_xero_sync_enabled(enabled=True) self.stdout.write("Xero seeding complete! enable_xero_sync is now True.") - def process_accounts(self, dry_run): + def process_accounts(self, dry_run: bool) -> int: """Phase 0: Update XeroAccount xero_ids from prod to dev Xero tenant. The backup includes XeroAccount records with prod xero_id values. @@ -210,10 +210,10 @@ def process_accounts(self, dry_run): account_name=account.name, defaults={ "xero_id": account.account_id, - "account_code": account.code, - "description": getattr(account, "description", None), - "account_type": account.type, - "tax_type": account.tax_type, + "account_code": account.code or None, + "description": getattr(account, "description", None) or None, + "account_type": account.type or None, + "tax_type": account.tax_type or None, "enable_payments": getattr( account, "enable_payments_to_account", False ), diff --git a/apps/workflow/tests/test_seed_xero_from_database.py b/apps/workflow/tests/test_seed_xero_from_database.py index 19d38e247..931a2ce39 100644 --- a/apps/workflow/tests/test_seed_xero_from_database.py +++ b/apps/workflow/tests/test_seed_xero_from_database.py @@ -10,14 +10,18 @@ """ from io import StringIO -from unittest.mock import patch +from types import SimpleNamespace +from unittest.mock import Mock, patch +from uuid import uuid4 from django.conf import settings from django.test import TestCase from django.utils import timezone from apps.company.models import Company +from apps.workflow.api.xero.transforms import sync_accounts from apps.workflow.management.commands.seed_xero_from_database import Command +from apps.workflow.models import XeroAccount SENTINEL_XERO_CONTACT_ID = "11111111-1111-1111-1111-111111111111" @@ -44,3 +48,81 @@ def test_refuses_when_db_name_ends_with_prod(self) -> None: company.refresh_from_db() self.assertEqual(company.xero_contact_id, SENTINEL_XERO_CONTACT_ID) + + +class XeroAccountSeedTests(TestCase): + @patch( + "apps.workflow.api.xero.transforms.process_xero_data", + return_value={}, + ) + def test_sync_normalises_empty_optional_text( + self, _process_xero_data_mock: Mock + ) -> None: + sync_accounts( + [ + SimpleNamespace( + account_id=uuid4(), + code="", + name="Uncoded account", + description="", + type="", + tax_type="", + enable_payments_to_account=False, + _updated_date_utc=timezone.now(), + ) + ] + ) + + account = XeroAccount.objects.get(account_name="Uncoded account") + self.assertIsNone(account.account_code) + self.assertIsNone(account.description) + self.assertIsNone(account.account_type) + self.assertIsNone(account.tax_type) + + @patch( + "apps.workflow.management.commands.seed_xero_from_database.process_xero_data", + return_value={}, + ) + @patch( + "apps.workflow.management.commands.seed_xero_from_database.get_tenant_id", + return_value="demo-tenant", + ) + @patch("apps.workflow.management.commands.seed_xero_from_database.AccountingApi") + def test_empty_xero_description_is_stored_as_null( + self, + accounting_api_mock: Mock, + _tenant_id_mock: Mock, + _process_xero_data_mock: Mock, + ) -> None: + prod_xero_id = uuid4() + demo_xero_id = uuid4() + modified_at = timezone.now() + XeroAccount.objects.create( + xero_id=prod_xero_id, + account_code="805", + account_name="Accrued Liabilities", + description="Production description", + account_type="CURRLIAB", + tax_type="NONE", + xero_last_modified=modified_at, + raw_json={}, + ) + accounting_api_mock.return_value.get_accounts.return_value.accounts = [ + SimpleNamespace( + account_id=demo_xero_id, + code="805", + name="Accrued Liabilities", + description="", + type="CURRLIAB", + tax_type="NONE", + enable_payments_to_account=False, + _updated_date_utc=modified_at, + ) + ] + + command = Command() + command.process_accounts(dry_run=False) + + account = XeroAccount.objects.get(account_name="Accrued Liabilities") + self.assertEqual(account.xero_id, demo_xero_id) + self.assertIsNone(account.description) diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 471ce09cf..79b9805ed 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -2146,7 +2146,6 @@ apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annota apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/api/xero/transforms.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def] apps/workflow/api/xero/transforms.py:0: error: Incompatible type for "order_date" of "PurchaseOrder" (got "Any | None", expected "str | date | Combinable") [misc] @@ -2235,7 +2234,6 @@ apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to u apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "convert_to_pascal_case" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "fetch_xero_entity_lookup" in typed context [no-untyped-call] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_accounts" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_contacts" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_employees" in typed context [no-untyped-call] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Call to untyped function "process_invoices" in typed context [no-untyped-call] @@ -2261,7 +2259,6 @@ apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] -apps/workflow/management/commands/seed_xero_from_database.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/seed_xero_from_database.py:0: error: Item "None" of "str | None" has no attribute "endswith" [union-attr] apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] apps/workflow/management/commands/start_xero_sync.py:0: error: Function is missing a type annotation [no-untyped-def] From 445afbf456b345a289254298e3720d297cfec207 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Fri, 31 Jul 2026 18:22:06 +1200 Subject: [PATCH 30/39] fix: drop the dead last_login API and UI surface Nothing in DocketWorks ever writes Staff.last_login. Authentication is JWT-only: SIMPLE_JWT leaves UPDATE_LAST_LOGIN at its False default, and CustomTokenObtainPairSerializer authenticates via authenticate(), which never emits the user_logged_in signal that Django's update_last_login receiver listens for. django.contrib.admin is not installed either, so there is no session-login path. The inherited AbstractBaseUser column has been NULL by construction. Admin > Staff nonetheless rendered a permanently blank "Last Login" column, and StaffFormModal round-tripped the value back to the server with no input bound to it. Worse, StaffCreateSerializer listed only wage_rate as read-only, so POST /api/accounts/staff/ accepted a client-supplied last_login -- an API client could forge a login time. Remove last_login from STAFF_API_FIELDS and from the admin staff table (fixing the empty-state colspan, which was already off by one), and drop the dead last_login/date_joined round-trip from StaffFormModal. The DB column stays; it belongs to AbstractBaseUser. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_018CvGn5ojk7NtQzr5WmzAEi --- apps/accounts/models.py | 5 +++- apps/accounts/serializers.py | 1 - apps/accounts/tests/test_staff_api.py | 27 ++++++++++++++++++++++ frontend/schema.yml | 10 -------- frontend/src/api/generated/api.ts | 2 -- frontend/src/components/StaffFormModal.vue | 10 -------- frontend/src/views/AdminStaffView.vue | 5 +--- 7 files changed, 32 insertions(+), 28 deletions(-) diff --git a/apps/accounts/models.py b/apps/accounts/models.py index fbe85628f..0a96d2ad3 100644 --- a/apps/accounts/models.py +++ b/apps/accounts/models.py @@ -103,7 +103,6 @@ class Staff(AbstractBaseUser, PermissionsMixin): "date_joined", "created_at", "updated_at", - "last_login", "groups", "user_permissions", ] @@ -111,6 +110,10 @@ class Staff(AbstractBaseUser, PermissionsMixin): # Internal fields not exposed via API (write-only or internal use). # `icon` is deliberately absent: it is written only by the dedicated icon # upload endpoint and read via the icon_url property. + # `last_login` is deliberately absent: authentication is JWT-only + # (`SIMPLE_JWT` leaves `UPDATE_LAST_LOGIN` at its `False` default and + # `authenticate()` never emits `user_logged_in`), so the inherited + # `AbstractBaseUser` column is never written and has no meaning to expose. STAFF_INTERNAL_FIELDS = [ "password", ] diff --git a/apps/accounts/serializers.py b/apps/accounts/serializers.py index efb545edf..a2869732a 100644 --- a/apps/accounts/serializers.py +++ b/apps/accounts/serializers.py @@ -92,7 +92,6 @@ class Meta: read_only_fields = [ "id", "wage_rate", - "last_login", "date_joined", "created_at", "updated_at", diff --git a/apps/accounts/tests/test_staff_api.py b/apps/accounts/tests/test_staff_api.py index b9fe6d174..0fd6e1c33 100644 --- a/apps/accounts/tests/test_staff_api.py +++ b/apps/accounts/tests/test_staff_api.py @@ -137,6 +137,33 @@ def test_create_leaves_a_new_staff_member_active(self) -> None: self.assertIsNone(created.date_left) self.assertTrue(created.is_currently_active) + def test_create_ignores_a_client_supplied_last_login(self) -> None: + """`last_login` is not part of the write contract. + + Authentication is JWT-only and nothing ever stamps the inherited + `AbstractBaseUser` column, so an API client must not be able to forge a + login time. The create serializer once listed only `wage_rate` as + read-only, which let this value through. + """ + response = self.client_api.post( + "/api/accounts/staff/", + { + "email": "forger@example.test", + "first_name": "For", + "last_name": "Ger", + "password": "TestPassword123!", + "base_wage_rate": 32.5, + "date_left": None, + "last_login": "2026-07-01T09:00:00Z", + }, + format="json", + ) + + self.assertEqual(response.status_code, 201, response.content) + self.assertNotIn("last_login", response.json()) + created = Staff.objects.get(email="forger@example.test") + self.assertIsNone(created.last_login) + def test_setting_date_left_offboards_a_staff_member(self) -> None: target = Staff.objects.create_user( email="leaving@example.test", diff --git a/frontend/schema.yml b/frontend/schema.yml index e372b6b50..94c814cf9 100644 --- a/frontend/schema.yml +++ b/frontend/schema.yml @@ -21719,11 +21719,6 @@ components: type: string format: date-time readOnly: true - last_login: - type: string - format: date-time - readOnly: true - nullable: true groups: type: array items: @@ -21746,7 +21741,6 @@ components: - first_name - icon_url - id - - last_login - last_name - updated_at - wage_rate @@ -21864,10 +21858,6 @@ components: created_at: type: string format: date-time - last_login: - type: string - format: date-time - nullable: true groups: type: array items: diff --git a/frontend/src/api/generated/api.ts b/frontend/src/api/generated/api.ts index 011dc2658..2f53ab219 100644 --- a/frontend/src/api/generated/api.ts +++ b/frontend/src/api/generated/api.ts @@ -466,7 +466,6 @@ const Staff = z.object({ date_joined: z.string().datetime({ offset: true }), created_at: z.string().datetime({ offset: true }), updated_at: z.string().datetime({ offset: true }), - last_login: z.string().datetime({ offset: true }).nullable(), groups: z.array(z.number().int()).optional(), user_permissions: z.array(z.number().int()).optional(), icon_url: z.string().nullable(), @@ -492,7 +491,6 @@ const StaffCreateRequest = z.object({ hours_sun: z.number().gt(-100).lt(100).optional(), date_joined: z.string().datetime({ offset: true }).optional(), created_at: z.string().datetime({ offset: true }).optional(), - last_login: z.string().datetime({ offset: true }).nullish(), groups: z.array(z.number().int()).optional(), user_permissions: z.array(z.number().int()).optional(), password: z.string().min(1).max(128), diff --git a/frontend/src/components/StaffFormModal.vue b/frontend/src/components/StaffFormModal.vue index 89fa11562..25c6e54f0 100644 --- a/frontend/src/components/StaffFormModal.vue +++ b/frontend/src/components/StaffFormModal.vue @@ -406,8 +406,6 @@ const form = ref({ is_superuser: false, groups: '', user_permissions: '', - last_login: '', - date_joined: '', date_left: '', }) const error = ref('') @@ -465,8 +463,6 @@ watch( Array.isArray(staff.user_permissions) && staff.user_permissions.length > 0 ? staff.user_permissions.join(', ') : '', - last_login: staff.last_login || '', - date_joined: staff.date_joined || '', date_left: staff.date_left || '', } } else { @@ -491,8 +487,6 @@ watch( is_superuser: false, groups: '', user_permissions: '', - last_login: '', - date_joined: '', date_left: '', } } @@ -518,8 +512,6 @@ async function submitForm() { // password and its confirmation, which must never reach the browser console. // Prepare base data - shared between validation and API call - const lastLogin = normalizeOptionalString(form.value.last_login) - const dateJoined = normalizeOptionalString(form.value.date_joined) const preferredName = normalizeOptionalString(form.value.preferred_name) const xeroUserId = normalizeOptionalString(form.value.xero_user_id) // date_left is always sent (null when blank) so an offboarded staff member @@ -561,8 +553,6 @@ async function submitForm() { // Handle optional fields - only include if they have a value ...(preferredName && { preferred_name: preferredName }), ...(xeroUserId && { xero_user_id: xeroUserId }), - ...(lastLogin && { last_login: lastLogin }), - ...(dateJoined && { date_joined: dateJoined }), } // Add password if provided diff --git a/frontend/src/views/AdminStaffView.vue b/frontend/src/views/AdminStaffView.vue index bf4393e74..4276f5d57 100644 --- a/frontend/src/views/AdminStaffView.vue +++ b/frontend/src/views/AdminStaffView.vue @@ -43,7 +43,6 @@ Last Name Is Office Staff Is SuperUser - Last Login Date Joined Actions @@ -78,7 +77,6 @@ ✔️ - {{ formatDateTime(staff.last_login) }} {{ formatDateTime(staff.date_joined) }}
@@ -99,7 +89,7 @@
- +
@@ -268,174 +128,6 @@ - - - - - - Create Invoice - - Choose how to invoice - {{ - props.pricingMethodology === 'fixed_price' - ? 'this quoted job' - : 'time & materials' - }} - - -
- -
-
- Quote total - {{ formatCurrency(quoteTotal) }} -
-
- Actual revenue to date - {{ - formatCurrency(actualSummary.rev) - }} -
-
- Already invoiced - {{ formatCurrency(invoiceTotal) }} -
-
- Current amount to invoice - {{ - formatCurrency(toBeInvoiced) - }} -
-
- - -
- - - - - -
-
- - - -
-
@@ -444,7 +136,7 @@ import debug from 'debug' const log = debug('job:actual') import { toLocalDateString } from '../../utils/dateUtils' -import { formatCurrency, formatDate } from '@/utils/string-formatting' +import { formatCurrency } from '@/utils/string-formatting' import { normalizeOptionalDecimal } from '@/utils/number' import { onMounted, ref, computed, reactive } from 'vue' import { useRouter } from 'vue-router' @@ -457,10 +149,8 @@ import { schemas } from '../../api/generated/api' import { useSmartCostLineDelete } from '../../composables/useSmartCostLineDelete' import { useCostSummary } from '../../composables/useCostSummary' import { useCostLineDrafts } from '@/composables/useCostLineDrafts' -import { useXeroConnection } from '../../composables/useXeroConnection' import { api } from '../../api/client' import { z } from 'zod' -import type { AxiosError } from 'axios' import type { KindOption } from '../shared/SmartCostLinesTable.vue' import { useStockStore } from '../../stores/stockStore' import SmartCostLinesTable from '../shared/SmartCostLinesTable.vue' @@ -473,18 +163,12 @@ import { DialogFooter, } from '../ui/dialog' import { Button } from '../ui/button' -import { Card, CardHeader, CardFooter, CardContent, CardDescription, CardTitle } from '../ui/card' -import { Input } from '../ui/input' -import { ExternalLink, Trash2 } from 'lucide-vue-next' -import { Badge } from '../ui/badge' import { useSaveFeedback } from '@/composables/useSaveFeedback' type CostLine = z.infer type CostSet = z.infer type KanbanStaff = z.infer type StockConsumeRequest = z.infer -type Invoice = z.infer -type XeroInvoiceCreateRequest = z.infer // Type guard functions to safely access meta and ext_refs function isDeliveryReceiptMeta(meta: unknown): meta is { source: string; po_number?: string } { @@ -526,11 +210,7 @@ function isStockExtRefs(extRefs: unknown): extRefs is { stock_id: string } { const props = defineProps<{ jobId: string - jobNumber: string pricingMethodology: string - quoted: boolean - fullyInvoiced: boolean - paid?: boolean }>() const jobActualSaveFeedback = useSaveFeedback(`job-actual:${props.jobId}`, { toastErrors: false, @@ -538,162 +218,17 @@ const jobActualSaveFeedback = useSaveFeedback(`job-actual:${props.jobId}`, { const emit = defineEmits<{ 'cost-line-changed': [] - 'quote-created': [] - 'quote-accepted': [] - 'invoice-created': [] - 'quote-deleted': [] - 'invoice-deleted': [] }>() const stockStore = useStockStore() -// Local state for invoices -const isCreatingInvoice = ref(false) -const deletingInvoiceId = ref(null) // Track which invoice is being deleted -const { xeroConnected } = useXeroConnection() - -// Local state for KPIs +// KPI chips. Invoice figures deliberately live in Finish Job only, so there is +// one authoritative place showing what the customer owes. const estimateTotal = ref(0) const quoteTotal = ref(0) const costsSummaryLoading = ref(false) - -// --- COMPUTED PROPERTIES --- -const invoices = ref>([]) const timeAndExpenses = computed(() => actualSummary.value.rev) -const invoiceTotal = computed(() => { - if (!invoices.value.length) return 0 - return invoices.value - .filter((inv) => inv.status !== 'VOIDED' && inv.status !== 'DELETED') - .reduce((sum, inv) => sum + (inv.total_excl_tax || 0), 0) -}) - -const toBeInvoiced = computed(() => { - // For fixed price jobs with a quote, use the quoted amount - // For T&M jobs or jobs without quotes, use the actual time & expenses - const amountToInvoice = - props.pricingMethodology === 'fixed_price' && quoteTotal.value > 0 - ? quoteTotal.value - : actualSummary.value.rev - - return amountToInvoice - invoiceTotal.value -}) - -const invoiceButtonText = computed(() => { - if (!xeroConnected.value) { - return 'Login to Xero first' - } - return 'Create Invoice' -}) - -// --- INVOICE MODAL --- -const showInvoiceModal = ref(false) -const selectedInvoiceMode = ref(null) -const invoicePercentInput = ref('') -const invoiceAmountInput = ref('') - -const createInvoice = () => { - selectedInvoiceMode.value = null - invoicePercentInput.value = '' - invoiceAmountInput.value = '' - showInvoiceModal.value = true -} - -function selectInvoiceMode(mode: string) { - selectedInvoiceMode.value = mode - invoicePercentInput.value = '' - invoiceAmountInput.value = '' -} - -async function executeCreateInvoice(mode: string) { - if (!props.jobId || isCreatingInvoice.value) return - - let percent: number | undefined - let amount: number | undefined - - if (mode === 'invoice_percent') { - const pct = parseFloat(invoicePercentInput.value) - if (isNaN(pct) || pct <= 0 || pct > 100) { - toast.error('Please enter a valid percentage (1-100)') - return - } - percent = pct - } - - if (mode === 'invoice_amount') { - const amt = parseFloat(invoiceAmountInput.value) - if (isNaN(amt) || amt <= 0) { - toast.error('Please enter a valid amount') - return - } - amount = amt - } - - showInvoiceModal.value = false - isCreatingInvoice.value = true - - try { - const body = { mode } as XeroInvoiceCreateRequest - if (percent !== undefined) body.percent = percent - if (amount !== undefined) body.amount = amount - - const response = await api.xero_create_invoice_create(body, { - params: { job_id: props.jobId }, - }) - if (!response?.success) { - const msgs = response?.messages?.length ? response.messages : ['Failed to create invoice'] - msgs.forEach((msg: string) => toast.error(msg)) - return - } - toast.success('Invoice created successfully!') - if (response.messages?.length) { - response.messages.forEach((msg: string) => toast.warning(msg)) - } - emit('invoice-created') - await loadInvoices() - } catch (err: unknown) { - let msg = 'Unexpected error while trying to create invoice.' - log('Error creating invoice:', err) - if ((err as AxiosError).isAxiosError) { - const axiosErr = err as AxiosError<{ message: string }> - const errorData = axiosErr.response?.data - if (typeof errorData === 'object' && errorData !== null && 'error' in errorData) { - msg = String((errorData as { error: string }).error) - } - } - toast.error(`Failed to create invoice: ${msg}`) - } finally { - isCreatingInvoice.value = false - } -} - -const goToInvoiceOnXero = (url: string | null | undefined) => { - if (url && url !== '#') { - window.open(url, '_blank') - } else { - toast.error('No online URL available for this invoice.') - } -} - -const deleteInvoiceOnXero = async (invoiceXeroId: string) => { - if (!props.jobId || deletingInvoiceId.value) return - deletingInvoiceId.value = invoiceXeroId - try { - await api.xero_delete_invoice_destroy(undefined, { - params: { job_id: props.jobId }, - queries: { xero_invoice_id: invoiceXeroId }, - }) - toast.success('Invoice deleted successfully!') - emit('invoice-deleted') - await loadInvoices() // Reload invoices after deletion - } catch (err) { - console.error('Error deleting invoice:', err) - toast.error('Failed to delete invoice.') - } finally { - deletingInvoiceId.value = null - } -} - const router = useRouter() const costLines = ref([]) @@ -777,18 +312,6 @@ async function loadCostsSummary() { } } -async function loadInvoices() { - try { - const response = await api.job_jobs_invoices_retrieve({ - params: { job_id: props.jobId }, - }) - // Zodios returns data directly, not wrapped in {success, data} - invoices.value = response.invoices || [] - } catch (error) { - log('Failed to load invoices:', error) - } -} - // Use the smart delete composable const { handleSmartDelete } = useSmartCostLineDelete({ costLines, @@ -899,7 +422,7 @@ async function handleCreateLine(line: CostLine): Promise { const costLineDraftSession = useCostLineDrafts({ costLines, createLine: handleCreateLine }) onMounted(async () => { - await Promise.all([loadStaff(), loadActualCosts(), loadCostsSummary(), loadInvoices()]) + await Promise.all([loadStaff(), loadActualCosts(), loadCostsSummary()]) }) // Use the cost summary composable (simple version for actual) diff --git a/frontend/src/components/job/JobCostAnalysisTab.vue b/frontend/src/components/job/JobCostAnalysisTab.vue deleted file mode 100644 index f8270976c..000000000 --- a/frontend/src/components/job/JobCostAnalysisTab.vue +++ /dev/null @@ -1,359 +0,0 @@ - - - - - diff --git a/frontend/src/components/job/JobFinishTab.vue b/frontend/src/components/job/JobFinishTab.vue new file mode 100644 index 000000000..4a821e3c3 --- /dev/null +++ b/frontend/src/components/job/JobFinishTab.vue @@ -0,0 +1,1095 @@ + + + + + diff --git a/frontend/src/components/job/JobViewTabs.vue b/frontend/src/components/job/JobViewTabs.vue index 203954c77..b79ef77f9 100644 --- a/frontend/src/components/job/JobViewTabs.vue +++ b/frontend/src/components/job/JobViewTabs.vue @@ -65,22 +65,20 @@
+
+
+
-
- -
({ + finishRetrieveMock: vi.fn(), + invoicesRetrieveMock: vi.fn(), + costsSummaryRetrieveMock: vi.fn(), + createInvoiceMock: vi.fn(), + deleteInvoiceMock: vi.fn(), +})) + +vi.mock('@/api/client', () => ({ + api: { + job_jobs_finish_retrieve: finishRetrieveMock, + job_jobs_invoices_retrieve: invoicesRetrieveMock, + job_jobs_costs_summary_retrieve: costsSummaryRetrieveMock, + job_jobs_finish_partial_update: vi.fn(), + xero_create_invoice_create: createInvoiceMock, + xero_delete_invoice_destroy: deleteInvoiceMock, + }, +})) + +vi.mock('@/composables/useXeroConnection', () => ({ + useXeroConnection: () => ({ xeroConnected: { value: true } }), +})) + +vi.mock('vue-sonner', () => ({ + toast: { error: vi.fn(), success: vi.fn(), warning: vi.fn() }, +})) + +import JobFinishTab from '../JobFinishTab.vue' + +/** + * The backend owns every figure here. These tests assert the component renders + * what the API returned and never recomputes it — the ADR 0020 boundary that + * KAN-323 exists to restore. + */ +const summary = (overrides: Record = {}) => ({ + basis: 'quote', + job_value_excl_gst: 1000, + valid_invoiced_excl_gst: 400, + outstanding_invoiced_incl_gst: 460, + remaining_to_invoice_excl_gst: 600, + remaining_gst: 90, + remaining_to_invoice_incl_gst: 690, + total_to_pay_incl_gst: 1150, + over_invoiced_excl_gst: 0, + ...overrides, +}) + +const checklist = () => ({ + time_entries_complete: false, + materials_complete: false, + customer_approval_confirmed: false, + updated_at: null, + updated_by_name: null, +}) + +const costSummary = () => ({ + estimate: { cost: 500, rev: 800, hours: 10, profitMargin: 60 }, + quote: { cost: 600, rev: 1000, hours: 12, profitMargin: 66 }, + actual: { cost: 550, rev: 900, hours: 11, profitMargin: 63 }, +}) + +// Mounting to document.body is required for the portalled invoice modal, so each +// test must tear its DOM down or the next test finds the previous modal. +let mounted: ReturnType | null = null + +function mountTab(pricingMethodology = 'fixed_price', jobStatus = 'in_progress') { + mounted = mount(JobFinishTab, { + props: { jobId: 'job-1', pricingMethodology, jobStatus }, + attachTo: document.body, + }) + return mounted +} + +function resetDom() { + mounted?.unmount() + mounted = null + document.body.innerHTML = '' +} + +const text = (wrapper: ReturnType, id: string) => + wrapper.find(`[data-automation-id="${id}"]`).text() + +// The invoice modal renders through a reka-ui portal, so it lands on document.body +// rather than inside the mounted wrapper. +const inModal = (id: string) => + document.body.querySelector(`[data-automation-id="${id}"]`) + +const modalText = (id: string) => { + const el = inModal(id) + if (!el) throw new Error(`${id} is not in the modal`) + return el.textContent ?? '' +} + +async function openInvoiceModal(wrapper: ReturnType) { + await wrapper.find('[data-automation-id="JobFinishTab-create-invoice"]').trigger('click') + await flushPromises() +} + +describe('JobFinishTab customer balance', () => { + beforeEach(() => { + vi.clearAllMocks() + finishRetrieveMock.mockResolvedValue({ summary: summary(), checklist: checklist() }) + invoicesRetrieveMock.mockResolvedValue({ invoices: [] }) + costsSummaryRetrieveMock.mockResolvedValue(costSummary()) + }) + + afterEach(resetDom) + + it('renders the subtotal, GST and Total to pay returned by the API', async () => { + const wrapper = mountTab() + await flushPromises() + + expect(text(wrapper, 'JobFinishTab-remaining-excl-gst')).toContain('600') + expect(text(wrapper, 'JobFinishTab-remaining-gst')).toContain('90') + expect(text(wrapper, 'JobFinishTab-total-to-pay')).toContain('1,150') + }) + + it('does not derive Total to pay from the other figures', async () => { + // A deliberately inconsistent payload: if the component recomputed the + // total it would show 1,290 rather than the server's answer. + finishRetrieveMock.mockResolvedValue({ + summary: summary({ total_to_pay_incl_gst: 42 }), + checklist: checklist(), + }) + const wrapper = mountTab() + await flushPromises() + + expect(text(wrapper, 'JobFinishTab-total-to-pay')).toContain('42') + }) + + it('shows the outstanding invoice balance when Xero is still owed money', async () => { + const wrapper = mountTab() + await flushPromises() + + expect(text(wrapper, 'JobFinishTab-outstanding-incl-gst')).toContain('460') + }) + + it('hides the outstanding line when every invoice is paid', async () => { + finishRetrieveMock.mockResolvedValue({ + summary: summary({ outstanding_invoiced_incl_gst: 0 }), + checklist: checklist(), + }) + const wrapper = mountTab() + await flushPromises() + + expect(wrapper.find('[data-automation-id="JobFinishTab-outstanding-incl-gst"]').exists()).toBe( + false, + ) + }) + + it('offers no invoice action once the job is fully covered', async () => { + finishRetrieveMock.mockResolvedValue({ + summary: summary({ + valid_invoiced_excl_gst: 1000, + remaining_to_invoice_excl_gst: 0, + remaining_gst: 0, + remaining_to_invoice_incl_gst: 0, + total_to_pay_incl_gst: 0, + }), + checklist: checklist(), + }) + const wrapper = mountTab() + await flushPromises() + + expect(wrapper.find('[data-automation-id="JobFinishTab-create-invoice"]').exists()).toBe(false) + expect(wrapper.find('[data-automation-id="JobFinishTab-fully-invoiced"]').exists()).toBe(true) + expect(text(wrapper, 'JobFinishTab-nothing-to-pay')).toContain('Nothing left to pay') + }) + + it('reports an over-invoiced job instead of a negative balance', async () => { + finishRetrieveMock.mockResolvedValue({ + summary: summary({ + job_value_excl_gst: 800, + valid_invoiced_excl_gst: 1000, + remaining_to_invoice_excl_gst: 0, + remaining_gst: 0, + remaining_to_invoice_incl_gst: 0, + outstanding_invoiced_incl_gst: 0, + total_to_pay_incl_gst: 0, + over_invoiced_excl_gst: 200, + }), + checklist: checklist(), + }) + const wrapper = mountTab() + await flushPromises() + + expect(text(wrapper, 'JobFinishTab-over-invoiced')).toContain('200') + }) + + it('re-reads the balance from the server after creating an invoice', async () => { + createInvoiceMock.mockResolvedValue({ success: true, messages: [] }) + const wrapper = mountTab() + await flushPromises() + expect(finishRetrieveMock).toHaveBeenCalledTimes(1) + + await openInvoiceModal(wrapper) + inModal('JobFinishTab-mode-invoice-full')!.click() + await flushPromises() + + expect(createInvoiceMock).toHaveBeenCalled() + expect(finishRetrieveMock).toHaveBeenCalledTimes(2) + }) + + it('re-reads the balance from the server after deleting an invoice', async () => { + invoicesRetrieveMock.mockResolvedValue({ + invoices: [ + { + id: 'inv-1', + xero_id: 'xero-1', + number: 'INV-001', + status: 'AUTHORISED', + date: '2026-08-01', + total_excl_tax: 400, + online_url: 'https://xero.example/inv-1', + }, + ], + }) + deleteInvoiceMock.mockResolvedValue({}) + const wrapper = mountTab() + await flushPromises() + + await wrapper + .findAll('button') + .filter((b) => b.classes().join(' ').includes('h-7')) + .at(1)! + .trigger('click') + await flushPromises() + + expect(deleteInvoiceMock).toHaveBeenCalled() + expect(finishRetrieveMock).toHaveBeenCalledTimes(2) + }) +}) + +describe('JobFinishTab invoice modes', () => { + beforeEach(() => { + vi.clearAllMocks() + finishRetrieveMock.mockResolvedValue({ summary: summary(), checklist: checklist() }) + invoicesRetrieveMock.mockResolvedValue({ invoices: [] }) + costsSummaryRetrieveMock.mockResolvedValue(costSummary()) + }) + + afterEach(resetDom) + + it('keeps all three fixed-price modes available', async () => { + const wrapper = mountTab('fixed_price') + await flushPromises() + await openInvoiceModal(wrapper) + + expect(inModal('JobFinishTab-mode-invoice-full')).not.toBeNull() + expect(inModal('JobFinishTab-mode-invoice-percent')).not.toBeNull() + expect(inModal('JobFinishTab-mode-invoice-amount')).not.toBeNull() + }) + + it('keeps both T&M modes available', async () => { + const wrapper = mountTab('time_materials') + await flushPromises() + await openInvoiceModal(wrapper) + + expect(inModal('JobFinishTab-mode-invoice-costs-to-date')).not.toBeNull() + expect(inModal('JobFinishTab-mode-invoice-amount')).not.toBeNull() + expect(inModal('JobFinishTab-mode-invoice-percent')).toBeNull() + }) + + it('offers invoicing before the work is complete', async () => { + const wrapper = mountTab('fixed_price', 'approved') + await flushPromises() + + expect(wrapper.find('[data-automation-id="JobFinishTab-create-invoice"]').exists()).toBe(true) + await openInvoiceModal(wrapper) + expect(modalText('JobFinishTab-mode-invoice-full')).toContain('in advance') + }) + + it('describes the remaining balance once the work is complete', async () => { + const wrapper = mountTab('fixed_price', 'recently_completed') + await flushPromises() + await openInvoiceModal(wrapper) + + expect(modalText('JobFinishTab-mode-invoice-full')).toContain('remaining quote balance') + }) +}) diff --git a/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts new file mode 100644 index 000000000..3250c024b --- /dev/null +++ b/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts @@ -0,0 +1,197 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' +import { mount, flushPromises } from '@vue/test-utils' + +const { + finishRetrieveMock, + invoicesRetrieveMock, + costsSummaryRetrieveMock, + checklistUpdateMock, + toastErrorMock, +} = vi.hoisted(() => ({ + finishRetrieveMock: vi.fn(), + invoicesRetrieveMock: vi.fn(), + costsSummaryRetrieveMock: vi.fn(), + checklistUpdateMock: vi.fn(), + toastErrorMock: vi.fn(), +})) + +vi.mock('@/api/client', () => ({ + api: { + job_jobs_finish_retrieve: finishRetrieveMock, + job_jobs_invoices_retrieve: invoicesRetrieveMock, + job_jobs_costs_summary_retrieve: costsSummaryRetrieveMock, + job_jobs_finish_partial_update: checklistUpdateMock, + xero_create_invoice_create: vi.fn(), + xero_delete_invoice_destroy: vi.fn(), + }, +})) + +vi.mock('@/composables/useXeroConnection', () => ({ + useXeroConnection: () => ({ xeroConnected: { value: true } }), +})) + +vi.mock('vue-sonner', () => ({ + toast: { error: toastErrorMock, success: vi.fn(), warning: vi.fn() }, +})) + +import JobFinishTab from '../JobFinishTab.vue' + +const summary = () => ({ + basis: 'quote', + job_value_excl_gst: 1000, + valid_invoiced_excl_gst: 0, + outstanding_invoiced_incl_gst: 0, + remaining_to_invoice_excl_gst: 1000, + remaining_gst: 150, + remaining_to_invoice_incl_gst: 1150, + total_to_pay_incl_gst: 1150, + over_invoiced_excl_gst: 0, +}) + +const checklist = (overrides: Record = {}) => ({ + time_entries_complete: false, + materials_complete: false, + customer_approval_confirmed: false, + updated_at: null, + updated_by_name: null, + ...overrides, +}) + +let mounted: ReturnType | null = null + +function mountTab(pricingMethodology: string) { + mounted = mount(JobFinishTab, { + props: { jobId: 'job-1', pricingMethodology, jobStatus: 'in_progress' }, + attachTo: document.body, + }) + return mounted +} + +const item = (wrapper: ReturnType, key: string) => + wrapper.find(`[data-automation-id="JobFinishTab-checklist-${key}"]`) + +describe('JobFinishTab completion checklist', () => { + beforeEach(() => { + vi.clearAllMocks() + finishRetrieveMock.mockResolvedValue({ summary: summary(), checklist: checklist() }) + invoicesRetrieveMock.mockResolvedValue({ invoices: [] }) + costsSummaryRetrieveMock.mockResolvedValue({ + estimate: { cost: 500, rev: 800, hours: 10, profitMargin: 60 }, + quote: { cost: 600, rev: 1000, hours: 12, profitMargin: 66 }, + actual: { cost: 550, rev: 900, hours: 11, profitMargin: 63 }, + }) + }) + + afterEach(() => { + mounted?.unmount() + mounted = null + document.body.innerHTML = '' + }) + + it('asks a T&M job to confirm time, materials and customer approval', async () => { + const wrapper = mountTab('time_materials') + await flushPromises() + + expect(item(wrapper, 'time_entries_complete').exists()).toBe(true) + expect(item(wrapper, 'materials_complete').exists()).toBe(true) + expect(item(wrapper, 'customer_approval_confirmed').exists()).toBe(true) + }) + + it('asks a fixed-price job only for customer approval, and shows the quote basis', async () => { + const wrapper = mountTab('fixed_price') + await flushPromises() + + expect(item(wrapper, 'time_entries_complete').exists()).toBe(false) + expect(item(wrapper, 'materials_complete').exists()).toBe(false) + expect(item(wrapper, 'customer_approval_confirmed').exists()).toBe(true) + expect(wrapper.find('[data-automation-id="JobFinishTab-quote-basis"]').text()).toContain( + '1,000', + ) + }) + + it('reflects confirmations already recorded on the job', async () => { + finishRetrieveMock.mockResolvedValue({ + summary: summary(), + checklist: checklist({ materials_complete: true }), + }) + const wrapper = mountTab('time_materials') + await flushPromises() + + expect((item(wrapper, 'materials_complete').element as HTMLInputElement).checked).toBe(true) + expect((item(wrapper, 'time_entries_complete').element as HTMLInputElement).checked).toBe(false) + }) + + it('sends only the item that changed', async () => { + checklistUpdateMock.mockResolvedValue({ + summary: summary(), + checklist: checklist({ materials_complete: true }), + }) + const wrapper = mountTab('time_materials') + await flushPromises() + + await item(wrapper, 'materials_complete').setValue(true) + await flushPromises() + + expect(checklistUpdateMock).toHaveBeenCalledWith( + { materials_complete: true }, + { params: { job_id: 'job-1' } }, + ) + }) + + it('sends false when a confirmation is withdrawn', async () => { + finishRetrieveMock.mockResolvedValue({ + summary: summary(), + checklist: checklist({ materials_complete: true }), + }) + checklistUpdateMock.mockResolvedValue({ summary: summary(), checklist: checklist() }) + const wrapper = mountTab('time_materials') + await flushPromises() + + await item(wrapper, 'materials_complete').setValue(false) + await flushPromises() + + expect(checklistUpdateMock).toHaveBeenCalledWith( + { materials_complete: false }, + { params: { job_id: 'job-1' } }, + ) + }) + + it('reverts the box and warns the user when the save fails', async () => { + checklistUpdateMock.mockRejectedValue(new Error('nope')) + const wrapper = mountTab('time_materials') + await flushPromises() + + await item(wrapper, 'materials_complete').setValue(true) + await flushPromises() + + expect(toastErrorMock).toHaveBeenCalledWith('Failed to save checklist') + expect((item(wrapper, 'materials_complete').element as HTMLInputElement).checked).toBe(false) + }) + + it('does not hide the invoice action behind the checklist', async () => { + const wrapper = mountTab('time_materials') + await flushPromises() + + expect((item(wrapper, 'customer_approval_confirmed').element as HTMLInputElement).checked).toBe( + false, + ) + expect(wrapper.find('[data-automation-id="JobFinishTab-create-invoice"]').exists()).toBe(true) + }) + + it('names who last changed a confirmation', async () => { + finishRetrieveMock.mockResolvedValue({ + summary: summary(), + checklist: checklist({ + customer_approval_confirmed: true, + updated_by_name: 'Office Person', + updated_at: '2026-08-01T09:00:00Z', + }), + }) + const wrapper = mountTab('time_materials') + await flushPromises() + + expect(wrapper.find('[data-automation-id="JobFinishTab-checklist"]').text()).toContain( + 'Office Person', + ) + }) +}) diff --git a/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts new file mode 100644 index 000000000..54dde9b07 --- /dev/null +++ b/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts @@ -0,0 +1,148 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' +import { mount, flushPromises } from '@vue/test-utils' + +const { finishRetrieveMock, invoicesRetrieveMock, costsSummaryRetrieveMock } = vi.hoisted(() => ({ + finishRetrieveMock: vi.fn(), + invoicesRetrieveMock: vi.fn(), + costsSummaryRetrieveMock: vi.fn(), +})) + +vi.mock('@/api/client', () => ({ + api: { + job_jobs_finish_retrieve: finishRetrieveMock, + job_jobs_invoices_retrieve: invoicesRetrieveMock, + job_jobs_costs_summary_retrieve: costsSummaryRetrieveMock, + job_jobs_finish_partial_update: vi.fn(), + xero_create_invoice_create: vi.fn(), + xero_delete_invoice_destroy: vi.fn(), + }, +})) + +vi.mock('@/composables/useXeroConnection', () => ({ + useXeroConnection: () => ({ xeroConnected: { value: true } }), +})) + +vi.mock('vue-sonner', () => ({ + toast: { error: vi.fn(), success: vi.fn(), warning: vi.fn() }, +})) + +import JobFinishTab from '../JobFinishTab.vue' + +/** + * KAN-222: office staff read labour budget, hours used and hours remaining + * without doing the subtraction, and an overrun shows as a positive number + * rather than a negative remainder. + */ +const summary = () => ({ + basis: 'quote', + job_value_excl_gst: 1000, + valid_invoiced_excl_gst: 0, + outstanding_invoiced_incl_gst: 0, + remaining_to_invoice_excl_gst: 1000, + remaining_gst: 150, + remaining_to_invoice_incl_gst: 1150, + total_to_pay_incl_gst: 1150, + over_invoiced_excl_gst: 0, +}) + +const checklist = () => ({ + time_entries_complete: false, + materials_complete: false, + customer_approval_confirmed: false, + updated_at: null, + updated_by_name: null, +}) + +let mounted: ReturnType | null = null + +function mountWithHours( + { + estimateHours, + quoteHours, + actualHours, + }: { estimateHours: number; quoteHours: number; actualHours: number }, + pricingMethodology = 'fixed_price', +) { + costsSummaryRetrieveMock.mockResolvedValue({ + estimate: { cost: 500, rev: 800, hours: estimateHours, profitMargin: 60 }, + quote: quoteHours > 0 ? { cost: 600, rev: 1000, hours: quoteHours, profitMargin: 66 } : null, + actual: { cost: 550, rev: 900, hours: actualHours, profitMargin: 63 }, + }) + mounted = mount(JobFinishTab, { + props: { jobId: 'job-1', pricingMethodology, jobStatus: 'in_progress' }, + attachTo: document.body, + }) + return mounted +} + +const hours = (wrapper: ReturnType, which: string) => + wrapper.find(`[data-automation-id="JobFinishTab-labour-${which}"]`).text() + +const remainingLabel = (wrapper: ReturnType) => + wrapper.find('[data-automation-id="JobFinishTab-labour-hours"]').text() + +describe('JobFinishTab labour hours', () => { + beforeEach(() => { + vi.clearAllMocks() + finishRetrieveMock.mockResolvedValue({ summary: summary(), checklist: checklist() }) + invoicesRetrieveMock.mockResolvedValue({ invoices: [] }) + }) + + afterEach(() => { + mounted?.unmount() + mounted = null + document.body.innerHTML = '' + }) + + it('shows budget, used and remaining for an under-budget job', async () => { + const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 12, actualHours: 8 }) + await flushPromises() + + expect(hours(wrapper, 'budget')).toBe('12') + expect(hours(wrapper, 'used')).toBe('8') + expect(hours(wrapper, 'remaining')).toBe('4') + expect(remainingLabel(wrapper)).toContain('Hours remaining') + }) + + it('shows zero remaining and no overrun exactly on budget', async () => { + const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 12, actualHours: 12 }) + await flushPromises() + + expect(hours(wrapper, 'remaining')).toBe('0') + expect(remainingLabel(wrapper)).toContain('Hours remaining') + expect(remainingLabel(wrapper)).not.toContain('Overrun') + }) + + it('shows an overrun as a positive number, not a negative remainder', async () => { + const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 12, actualHours: 15 }) + await flushPromises() + + expect(hours(wrapper, 'remaining')).toBe('3') + expect(remainingLabel(wrapper)).toContain('Overrun') + expect(hours(wrapper, 'remaining')).not.toContain('-') + }) + + it('budgets a fixed-price job from its quote hours', async () => { + const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 12, actualHours: 5 }) + await flushPromises() + + expect(hours(wrapper, 'budget')).toBe('12') + }) + + it('budgets a fixed-price job with no quote from its estimate hours', async () => { + const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 0, actualHours: 5 }) + await flushPromises() + + expect(hours(wrapper, 'budget')).toBe('10') + }) + + it('budgets a T&M job from its estimate hours', async () => { + const wrapper = mountWithHours( + { estimateHours: 10, quoteHours: 12, actualHours: 5 }, + 'time_materials', + ) + await flushPromises() + + expect(hours(wrapper, 'budget')).toBe('10') + }) +}) diff --git a/frontend/src/constants/job-tabs.ts b/frontend/src/constants/job-tabs.ts index ce19afadf..b6403253f 100644 --- a/frontend/src/constants/job-tabs.ts +++ b/frontend/src/constants/job-tabs.ts @@ -9,7 +9,7 @@ export const JobTabsSchema = z.enum([ 'quote', 'actual', 'financial', - 'costAnalysis', + 'finishJob', 'jobSettings', 'history', 'attachments', diff --git a/frontend/tests/job/job-xero-invoice.spec.ts b/frontend/tests/job/job-xero-invoice.spec.ts index 63e9da3d9..31d2abbde 100644 --- a/frontend/tests/job/job-xero-invoice.spec.ts +++ b/frontend/tests/job/job-xero-invoice.spec.ts @@ -12,7 +12,7 @@ const getJobIdFromUrl = (url: string): string => { test.describe('job xero invoice', () => { test.setTimeout(120000) - test('create invoice in Xero from Actual tab', async ({ + test('invoice a job from Finish Job and see the balance settle', async ({ authenticatedPage: page, sharedEditJobUrl, }) => { @@ -21,12 +21,18 @@ test.describe('job xero invoice', () => { await page.goto(sharedEditJobUrl) await page.waitForLoadState('networkidle') - await autoId(page, 'JobViewTabs-actual').click() + await autoId(page, 'JobViewTabs-finishJob').click() + + // The balance is server-owned; the tab must render it before offering to invoice. + await expect(autoId(page, 'JobFinishTab-total-to-pay')).toBeVisible({ timeout: 10000 }) + const remaining = autoId(page, 'JobFinishTab-remaining-excl-gst') + await expect(remaining).toBeVisible() + await expect(remaining).not.toHaveText(/\$0\.00/) const invoiceItems = page.locator('ul[role="list"] li') const initialCount = await invoiceItems.count() - const createInvoiceButton = page.getByRole('button', { name: /Create .*Invoice/ }) + const createInvoiceButton = autoId(page, 'JobFinishTab-create-invoice') await expect(createInvoiceButton).toBeVisible({ timeout: 10000 }) const responsePromise = page.waitForResponse( @@ -41,12 +47,9 @@ test.describe('job xero invoice', () => { await createInvoiceButton.click() - // Modal should appear — select the primary invoice mode - const invoiceRemainingButton = page.getByRole('button', { - name: /Invoice remaining quote/, - }) - await expect(invoiceRemainingButton).toBeVisible({ timeout: 10000 }) - await invoiceRemainingButton.click() + const invoiceFullButton = autoId(page, 'JobFinishTab-mode-invoice-full') + await expect(invoiceFullButton).toBeVisible({ timeout: 10000 }) + await invoiceFullButton.click() const response = await responsePromise if (!response.ok()) { @@ -57,5 +60,11 @@ test.describe('job xero invoice', () => { } await expect(invoiceItems).toHaveCount(initialCount + 1, { timeout: 20000 }) + + // KAN-323: a fully invoiced job shows nothing remaining and stops asking for + // another invoice, rather than offering a ceremonial $0 one. + await expect(remaining).toHaveText(/\$0\.00/, { timeout: 20000 }) + await expect(autoId(page, 'JobFinishTab-fully-invoiced')).toBeVisible() + await expect(createInvoiceButton).toHaveCount(0) }) }) From b6584c9c51df4d677ff367539b10f30690103848 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Sat, 1 Aug 2026 10:09:48 +1200 Subject: [PATCH 35/39] fix: stack the Finish Job labour tiles on narrow screens A fixed three-column grid put the labour budget, used and remaining figures into roughly 100px each on a phone, which is where staff read them while standing at the job. They stack below the sm breakpoint now. KAN-323 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01ACLSprAHJSeQErMxQqLKDH --- frontend/src/components/job/JobFinishTab.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/job/JobFinishTab.vue b/frontend/src/components/job/JobFinishTab.vue index 4a821e3c3..b4aed1eb1 100644 --- a/frontend/src/components/job/JobFinishTab.vue +++ b/frontend/src/components/job/JobFinishTab.vue @@ -288,7 +288,10 @@
-
+
Labour budget
Date: Sat, 1 Aug 2026 17:10:59 +1200 Subject: [PATCH 36/39] refactor: front-desk checklist as Job fields, not its own table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The completion checklist shipped as a separate JobCompletionChecklist table with a OneToOne back to Job. Being 1:1, that was columns with a join in front of them, and it cost more than the join: a get_completion_checklist() that returned an unsaved instance for jobs with no row yet, updated_at/updated_by columns that recorded who last touched the checklist rather than who ticked what, and a service that hand-wrote a JobEvent per item. Job already does all of that. _FIELD_HANDLERS turns any tracked field change into a job-history event, which is where "Marked as paid" comes from. So the items are Job booleans now, the table and its service are gone, and the per-item audit is the machinery that was already there. The items also changed to the questions the front desk actually works through: foreman signed off, timesheets collected, materials checked, customer called, released. Same five on every job — urgency differs between T&M and quoted work, but that is a note under the list, not a branch in the schema, so the conditional rendering goes too. collected is renamed to released rather than replaced. It meant the same thing and was never writable — no serializer, endpoint, admin or UI ever set it — so every row holds the default and the rename carries nothing stale forward. This also drops customer_approval_confirmed: a customer is not handed work they have just rejected, so the tick is implied by release for a collection, and for a delivery it cannot be answered at the moment it would be ticked. Migration 0010 is replaced rather than added to, since nothing has been pushed. KAN-323 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01ACLSprAHJSeQErMxQqLKDH --- .../0010_job_completion_checklist.py | 66 ---- .../0010_job_completion_checklist_fields.py | 53 +++ apps/job/models/__init__.py | 2 - apps/job/models/job.py | 41 ++- apps/job/models/job_completion_checklist.py | 64 ---- apps/job/models/job_event.py | 35 +- apps/job/serializers/job_serializer.py | 41 +-- apps/job/services/__init__.py | 8 - .../job_completion_checklist_service.py | 97 ------ apps/job/tests/test_completion_checklist.py | 321 +++++------------- apps/job/tests/test_job_event_tracking.py | 28 +- apps/job/views/job_rest_views.py | 45 ++- frontend/schema.yml | 48 +-- frontend/src/api/generated/api.ts | 18 +- frontend/src/components/job/JobFinishTab.vue | 47 ++- .../__tests__/JobFinishTab.balance.test.ts | 10 +- .../__tests__/JobFinishTab.checklist.test.ts | 114 ++++--- .../JobFinishTab.labourHours.test.ts | 10 +- mypy-baseline.txt | 1 - 19 files changed, 405 insertions(+), 644 deletions(-) delete mode 100644 apps/job/migrations/0010_job_completion_checklist.py create mode 100644 apps/job/migrations/0010_job_completion_checklist_fields.py delete mode 100644 apps/job/models/job_completion_checklist.py delete mode 100644 apps/job/services/job_completion_checklist_service.py diff --git a/apps/job/migrations/0010_job_completion_checklist.py b/apps/job/migrations/0010_job_completion_checklist.py deleted file mode 100644 index 71af30bbf..000000000 --- a/apps/job/migrations/0010_job_completion_checklist.py +++ /dev/null @@ -1,66 +0,0 @@ -# Generated by Django 6.0.7 on 2026-07-31 21:32 - -import uuid - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ("job", "0009_text_unset_constraints"), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name="JobCompletionChecklist", - fields=[ - ( - "id", - models.UUIDField( - default=uuid.uuid4, - editable=False, - primary_key=True, - serialize=False, - ), - ), - ("time_entries_complete", models.BooleanField(default=False)), - ("materials_complete", models.BooleanField(default=False)), - ("customer_approval_confirmed", models.BooleanField(default=False)), - ( - "updated_at", - models.DateTimeField( - blank=True, - help_text="When an item was last changed; NULL until the first change.", - null=True, - ), - ), - ( - "job", - models.OneToOneField( - on_delete=django.db.models.deletion.CASCADE, - related_name="completion_checklist", - to="job.job", - ), - ), - ( - "updated_by", - models.ForeignKey( - blank=True, - help_text="Who last changed an item; NULL until the first change.", - null=True, - on_delete=django.db.models.deletion.PROTECT, - related_name="+", - to=settings.AUTH_USER_MODEL, - ), - ), - ], - options={ - "verbose_name": "Job Completion Checklist", - "verbose_name_plural": "Job Completion Checklists", - }, - ), - ] diff --git a/apps/job/migrations/0010_job_completion_checklist_fields.py b/apps/job/migrations/0010_job_completion_checklist_fields.py new file mode 100644 index 000000000..99b380680 --- /dev/null +++ b/apps/job/migrations/0010_job_completion_checklist_fields.py @@ -0,0 +1,53 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + """Front-desk completion checklist as Job fields. + + ``collected`` is renamed rather than replaced: it meant the same thing and was + never writable (no serializer, endpoint, admin or UI ever set it), so every + row holds the default and the rename carries no stale data forward. + """ + + dependencies = [ + ("job", "0009_text_unset_constraints"), + ] + + operations = [ + migrations.RenameField( + model_name="job", + old_name="collected", + new_name="released", + ), + migrations.AlterField( + model_name="job", + name="released", + field=models.BooleanField( + default=False, + help_text=( + "The job has left our possession, by collection, delivery or " + "on-site install." + ), + ), + ), + migrations.AddField( + model_name="job", + name="foreman_signed_off", + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name="job", + name="timesheets_collected", + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name="job", + name="materials_checked", + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name="job", + name="customer_called", + field=models.BooleanField(default=False), + ), + ] diff --git a/apps/job/models/__init__.py b/apps/job/models/__init__.py index b92540367..fa3673ec3 100644 --- a/apps/job/models/__init__.py +++ b/apps/job/models/__init__.py @@ -2,7 +2,6 @@ from .costing import CostLine, CostSet from .job import Job -from .job_completion_checklist import JobCompletionChecklist from .job_delta_rejection import JobDeltaRejection from .job_event import JobEvent from .job_file import JobFile @@ -14,7 +13,6 @@ "CostLine", "CostSet", "Job", - "JobCompletionChecklist", "JobDeltaRejection", "JobEvent", "JobFile", diff --git a/apps/job/models/job.py b/apps/job/models/job.py index 66fed6ab1..676cc5f3a 100644 --- a/apps/job/models/job.py +++ b/apps/job/models/job.py @@ -307,8 +307,19 @@ class Job(models.Model): # Shop job has no company (company_id is None) job_is_valid = models.BooleanField(default=False) - collected: bool = models.BooleanField(default=False) paid: bool = models.BooleanField(default=False) + + # Front-desk completion checklist. Each is a fact only a person knows, so + # none of them can be derived. Ticking one writes a job-history event through + # _FIELD_HANDLERS below; nothing here blocks invoicing or moves the job. + foreman_signed_off = models.BooleanField(default=False) + timesheets_collected = models.BooleanField(default=False) + materials_checked = models.BooleanField(default=False) + customer_called = models.BooleanField(default=False) + released = models.BooleanField( + default=False, + help_text="The job has left our possession, by collection, delivery or on-site install.", + ) fully_invoiced: bool = models.BooleanField( default=False, help_text="The total value of invoices for this job matches the total value of the job.", @@ -1146,10 +1157,30 @@ def _handle_rdti_type_change(_self_job, old_type, new_type): "payment_updated", "Paid", ), - "collected": _handle_boolean_change( - "job_collected", - "collection_updated", - "Collected", + "foreman_signed_off": _handle_boolean_change( + "completion_checklist_updated", + "completion_checklist_updated", + "Foreman sign-off", + ), + "timesheets_collected": _handle_boolean_change( + "completion_checklist_updated", + "completion_checklist_updated", + "Timesheets collected", + ), + "materials_checked": _handle_boolean_change( + "completion_checklist_updated", + "completion_checklist_updated", + "Materials checked", + ), + "customer_called": _handle_boolean_change( + "completion_checklist_updated", + "completion_checklist_updated", + "Customer called", + ), + "released": _handle_boolean_change( + "completion_checklist_updated", + "completion_checklist_updated", + "Job released", ), "complex_job": _handle_boolean_change( "job_updated", diff --git a/apps/job/models/job_completion_checklist.py b/apps/job/models/job_completion_checklist.py deleted file mode 100644 index 58e4aa2bd..000000000 --- a/apps/job/models/job_completion_checklist.py +++ /dev/null @@ -1,64 +0,0 @@ -import uuid - -from django.db import models - -from apps.accounts.models import Staff - - -class JobCompletionChecklist(models.Model): - """Staff confirmations recorded while finishing a job. - - Deliberately advisory: nothing here blocks invoicing, changes job status, - creates tasks, or nags. Its only job is to remember what a staff member - confirmed, and to leave an audit trail when a confirmation is withdrawn. - - ``updated_at`` and ``updated_by`` are NULL until the first confirmation is - recorded — a row can exist with nothing yet confirmed. - """ - - # The confirmable items, in display order. Serializers and the update - # service derive their accepted keys from this tuple, so adding an item here - # is the only change needed to expose it. - ITEM_FIELDS = ( - "time_entries_complete", - "materials_complete", - "customer_approval_confirmed", - ) - - # Item key → the label used in job-history events. - ITEM_LABELS = { - "time_entries_complete": "All time entered", - "materials_complete": "All materials entered", - "customer_approval_confirmed": "Customer approval confirmed", - } - - id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - job = models.OneToOneField( - "job.Job", - on_delete=models.CASCADE, - related_name="completion_checklist", - ) - time_entries_complete = models.BooleanField(default=False) - materials_complete = models.BooleanField(default=False) - customer_approval_confirmed = models.BooleanField(default=False) - updated_at = models.DateTimeField( - null=True, - blank=True, - help_text="When an item was last changed; NULL until the first change.", - ) - updated_by = models.ForeignKey( - Staff, - on_delete=models.PROTECT, - null=True, - blank=True, - related_name="+", - help_text="Who last changed an item; NULL until the first change.", - ) - - class Meta: - verbose_name = "Job Completion Checklist" - verbose_name_plural = "Job Completion Checklists" - - def __str__(self) -> str: - confirmed = sum(1 for field in self.ITEM_FIELDS if getattr(self, field)) - return f"Checklist for {self.job.name}: {confirmed}/{len(self.ITEM_FIELDS)}" diff --git a/apps/job/models/job_event.py b/apps/job/models/job_event.py index 4d204a4f0..32fa55e00 100644 --- a/apps/job/models/job_event.py +++ b/apps/job/models/job_event.py @@ -49,20 +49,20 @@ def _truncate_change(label: str, old, new) -> str: def _completion_confirmation_descriptor( - subject: str, + confirmed: str, withdrawn: str ) -> Callable[[str, str], str]: - """Descriptor factory for Finish Job checklist confirmations. + """Descriptor factory for front-desk checklist items. - A withdrawn confirmation reads as plainly as a granted one, since withdrawing - is the change most worth being able to find later. Values are the "Yes"/"No" - strings written by the checklist service. + Both wordings are given explicitly rather than built from one subject: an + unticking is the change most worth finding later, so it earns a sentence that + reads properly instead of a negated one that does not. """ def descriptor(old: str, new: str) -> str: if _truthy(new): - return f"Confirmed {subject}" + return confirmed else: - return f"Withdrew confirmation of {subject}" + return withdrawn return descriptor @@ -85,16 +85,21 @@ def _quote_acceptance_descriptor(old, new) -> str: "Marked as complex job" if _truthy(new) else "Unmarked as complex job" ), "Paid": lambda old, new: ("Marked as paid" if _truthy(new) else "Marked as unpaid"), - "Collected": lambda old, new: ( - "Marked as collected" if _truthy(new) else "Marked as not collected" - ), "Quote acceptance date": _quote_acceptance_descriptor, - "All time entered": _completion_confirmation_descriptor("all time entered"), - "All materials entered": _completion_confirmation_descriptor( - "all materials entered" + "Foreman sign-off": _completion_confirmation_descriptor( + "Foreman signed the job off", "Foreman sign-off withdrawn" + ), + "Timesheets collected": _completion_confirmation_descriptor( + "Timesheets collected from the workshop", "Timesheet collection unconfirmed" + ), + "Materials checked": _completion_confirmation_descriptor( + "Materials checked on the job", "Materials check unconfirmed" + ), + "Customer called": _completion_confirmation_descriptor( + "Customer called", "Customer call unconfirmed" ), - "Customer approval confirmed": _completion_confirmation_descriptor( - "customer approval" + "Job released": _completion_confirmation_descriptor( + "Job released", "Job release withdrawn" ), "Internal notes": lambda old, new: _truncate_change("Notes", old, new), "Job description": lambda old, new: _truncate_change("Description", old, new), diff --git a/apps/job/serializers/job_serializer.py b/apps/job/serializers/job_serializer.py index 31a027214..9713f08cd 100644 --- a/apps/job/serializers/job_serializer.py +++ b/apps/job/serializers/job_serializer.py @@ -10,7 +10,7 @@ from apps.accounting.models.quote import Quote from apps.accounting.services.finish_job_summary import FinishJobSummary from apps.company.models import Company, Person -from apps.job.models import Job, JobCompletionChecklist, JobEvent, JobFile +from apps.job.models import Job, JobEvent, JobFile from apps.workflow.models import XeroPayItem from apps.workflow.serializers import AppErrorResponseSerializer from apps.workflow.serializers_base import NullUnsetModelSerializer @@ -852,7 +852,7 @@ class FinishJobPayload(TypedDict): """What the Finish Job endpoint serializes: a balance plus a checklist.""" summary: FinishJobSummary - checklist: JobCompletionChecklist + checklist: Job class FinishJobSummarySerializer(serializers.Serializer[FinishJobSummary]): @@ -890,37 +890,32 @@ class FinishJobSummarySerializer(serializers.Serializer[FinishJobSummary]): ) -class JobCompletionChecklistSerializer(serializers.Serializer[JobCompletionChecklist]): - """Read shape for the Finish Job completion checklist. +class JobCompletionChecklistSerializer(serializers.Serializer[Job]): + """Read shape for the front-desk completion checklist. - updated_at and updated_by_name are null until a staff member first changes an - item, including for the unsaved all-false checklist of a job nobody has - confirmed anything on. + The items are Job fields, so each tick is audited by the job's own + field-change machinery. Who ticked what, and when, is in the job history. """ - time_entries_complete = serializers.BooleanField(read_only=True) - materials_complete = serializers.BooleanField(read_only=True) - customer_approval_confirmed = serializers.BooleanField(read_only=True) - updated_at = serializers.DateTimeField(read_only=True, allow_null=True) - updated_by_name = serializers.SerializerMethodField() - - @extend_schema_field(serializers.CharField(allow_null=True)) - def get_updated_by_name(self, obj: JobCompletionChecklist) -> Optional[str]: - if not obj.updated_by: - return None - return obj.updated_by.get_display_full_name() + foreman_signed_off = serializers.BooleanField(read_only=True) + timesheets_collected = serializers.BooleanField(read_only=True) + materials_checked = serializers.BooleanField(read_only=True) + customer_called = serializers.BooleanField(read_only=True) + released = serializers.BooleanField(read_only=True) class JobCompletionChecklistUpdateSerializer(serializers.Serializer[None]): """Partial update shape: send only the items being changed. - Every item is optional, and unknown keys are rejected by the service rather - than dropped, so a client typo is a 400 instead of a silent no-op. + Every item is optional, and unknown keys are rejected by the view rather than + dropped, so a client typo is a 400 instead of a silent no-op. """ - time_entries_complete = serializers.BooleanField(required=False) - materials_complete = serializers.BooleanField(required=False) - customer_approval_confirmed = serializers.BooleanField(required=False) + foreman_signed_off = serializers.BooleanField(required=False) + timesheets_collected = serializers.BooleanField(required=False) + materials_checked = serializers.BooleanField(required=False) + customer_called = serializers.BooleanField(required=False) + released = serializers.BooleanField(required=False) class JobFinishResponseSerializer(serializers.Serializer[FinishJobPayload]): diff --git a/apps/job/services/__init__.py b/apps/job/services/__init__.py index 71e07426f..6eb43df58 100644 --- a/apps/job/services/__init__.py +++ b/apps/job/services/__init__.py @@ -31,11 +31,6 @@ serialize_draft_lines, serialize_validation_report, ) - from .job_completion_checklist_service import ( - ChecklistUpdateError, - get_completion_checklist, - update_completion_checklist, - ) from .job_profitability_report import JobProfitabilityReportService from .job_rest_service import ( DeltaValidationError, @@ -115,7 +110,6 @@ "AutoArchiveService", "ChatFileService", "ChatService", - "ChecklistUpdateError", "ChecksumInput", "DataIntegrityService", "DeltaValidationError", @@ -163,7 +157,6 @@ "format_retail_line_total", "generate_delivery_docket", "get_bill_rate_multiplier", - "get_completion_checklist", "get_job_for_delivery_docket_pdf", "get_job_for_workshop_pdf", "get_job_total_value", @@ -192,6 +185,5 @@ "serialize_validation_report", "sync_job_folder", "to_decimal", - "update_completion_checklist", "wait_until_file_ready", ] diff --git a/apps/job/services/job_completion_checklist_service.py b/apps/job/services/job_completion_checklist_service.py deleted file mode 100644 index 88be54ca9..000000000 --- a/apps/job/services/job_completion_checklist_service.py +++ /dev/null @@ -1,97 +0,0 @@ -"""Reads and partial updates for the Job completion checklist. - -Every accepted change writes one job-history event naming the item, its old and -new value, the acting staff member and the time, so a withdrawn confirmation is -as visible as a granted one. -""" - -from django.db import transaction -from django.utils import timezone - -from apps.accounts.models import Staff -from apps.job.models import Job -from apps.job.models.job_completion_checklist import JobCompletionChecklist -from apps.job.models.job_event import JobEvent - -CHECKLIST_UPDATED_EVENT = "completion_checklist_updated" - - -class ChecklistUpdateError(ValueError): - """Raised when a checklist update names an unknown item or a non-boolean.""" - - -def get_completion_checklist(job: Job) -> JobCompletionChecklist: - """The job's checklist. - - A job nobody has confirmed anything on gets an unsaved all-false checklist - rather than a row written during a read. - """ - checklist = JobCompletionChecklist.objects.filter(job=job).first() - if not checklist: - return JobCompletionChecklist(job=job) - else: - return checklist - - -def update_completion_checklist( - job: Job, updates: dict[str, bool], staff: Staff -) -> JobCompletionChecklist: - """Apply a partial checklist update and audit each item that changed. - - Raises ChecklistUpdateError for unknown item keys or non-boolean values, so a - typo in a client payload is a 400 rather than a silently ignored field. - """ - unknown = sorted(set(updates) - set(JobCompletionChecklist.ITEM_FIELDS)) - if unknown: - raise ChecklistUpdateError( - f"Unknown checklist item(s): {', '.join(unknown)}. " - f"Valid items: {', '.join(JobCompletionChecklist.ITEM_FIELDS)}." - ) - - non_boolean = sorted( - key for key, value in updates.items() if not isinstance(value, bool) - ) - if non_boolean: - raise ChecklistUpdateError( - f"Checklist item(s) must be true or false: {', '.join(non_boolean)}." - ) - - with transaction.atomic(): - checklist, _ = JobCompletionChecklist.objects.get_or_create(job=job) - - changed = { - key: value - for key, value in updates.items() - if getattr(checklist, key) != value - } - if not changed: - return checklist - - for key, new_value in changed.items(): - _record_change(job, staff, key, getattr(checklist, key), new_value) - setattr(checklist, key, new_value) - - checklist.updated_at = timezone.now() - checklist.updated_by = staff - checklist.save() - - return checklist - - -def _record_change( - job: Job, staff: Staff, item: str, old_value: bool, new_value: bool -) -> None: - JobEvent.objects.create( - job=job, - staff=staff, - event_type=CHECKLIST_UPDATED_EVENT, - detail={ - "changes": [ - { - "field_name": JobCompletionChecklist.ITEM_LABELS[item], - "old_value": "Yes" if old_value else "No", - "new_value": "Yes" if new_value else "No", - } - ] - }, - ) diff --git a/apps/job/tests/test_completion_checklist.py b/apps/job/tests/test_completion_checklist.py index ab763abec..adf4f2966 100644 --- a/apps/job/tests/test_completion_checklist.py +++ b/apps/job/tests/test_completion_checklist.py @@ -1,29 +1,28 @@ -"""Tests for the Finish Job completion checklist. +"""Tests for the front-desk completion checklist. -The checklist is advisory by design: these tests pin both that changes are -audited and that ticking a box never affects what a user can invoice or what -status a job is in. +The items are Job fields, so the audit trail comes from the job's own +field-change machinery. These tests pin that each tick is attributed and that +ticking nothing still lets a job be invoiced — the checklist records, it does +not gate. """ from decimal import Decimal from django.urls import reverse from django.utils import timezone +from rest_framework.response import Response from apps.accounting.services.invoice_calculation import calculate_invoice_amount from apps.accounts.models import Staff from apps.company.models import Company -from apps.job.models import Job, JobCompletionChecklist, JobEvent -from apps.job.services.job_completion_checklist_service import ( - CHECKLIST_UPDATED_EVENT, - ChecklistUpdateError, - get_completion_checklist, - update_completion_checklist, -) -from apps.testing import BaseAPITestCase, BaseTestCase +from apps.job.models import Job, JobEvent +from apps.job.views.job_rest_views import CHECKLIST_FIELDS +from apps.testing import BaseAPITestCase +CHECKLIST_EVENT = "completion_checklist_updated" -class TestCompletionChecklistService(BaseTestCase): + +class TestCompletionChecklist(BaseAPITestCase): def setUp(self) -> None: self.client_obj = Company.objects.create( name="Test Company", @@ -35,184 +34,136 @@ def setUp(self) -> None: pricing_methodology="time_materials", ) self.job.save(staff=self.test_staff) + self.url = reverse("jobs:job_finish_rest", args=[self.job.id]) + # Ticking an item is an office action; the shared test_staff is + # deliberately neither office nor workshop. + self.office_staff = Staff.objects.create_user( + email="office@example.com", + password="testpass", + first_name="Office", + last_name="Person", + is_office_staff=True, + ) + self.client.force_login(self.office_staff) + + def _patch(self, payload: dict[str, object]) -> Response: + return self.client.patch(self.url, data=payload, format="json") # --- Reading --- - def test_unconfirmed_job_reads_as_all_false_without_writing_a_row(self) -> None: - checklist = get_completion_checklist(self.job) + def test_a_new_job_has_nothing_ticked(self) -> None: + response = self.client.get(self.url) - self.assertFalse(checklist.time_entries_complete) - self.assertFalse(checklist.materials_complete) - self.assertFalse(checklist.customer_approval_confirmed) - self.assertIsNone(checklist.updated_at) - self.assertIsNone(checklist.updated_by) - self.assertFalse(JobCompletionChecklist.objects.filter(job=self.job).exists()) + self.assertEqual(response.status_code, 200) + for field in CHECKLIST_FIELDS: + self.assertFalse(response.data["checklist"][field], msg=field) - # --- Partial updates --- + def test_every_item_is_exposed(self) -> None: + """The API shape and the field tuple must not drift apart.""" + response = self.client.get(self.url) - def test_update_touches_only_the_named_item(self) -> None: - update_completion_checklist( - self.job, {"materials_complete": True}, self.test_staff - ) + self.assertEqual(set(response.data["checklist"].keys()), set(CHECKLIST_FIELDS)) - checklist = get_completion_checklist(self.job) - self.assertTrue(checklist.materials_complete) - self.assertFalse(checklist.time_entries_complete) - self.assertFalse(checklist.customer_approval_confirmed) + # --- Updating --- - def test_update_records_who_and_when(self) -> None: - checklist = update_completion_checklist( - self.job, {"time_entries_complete": True}, self.test_staff - ) + def test_ticking_one_item_leaves_the_others_alone(self) -> None: + response = self._patch({"materials_checked": True}) - self.assertEqual(checklist.updated_by, self.test_staff) - self.assertIsNotNone(checklist.updated_at) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.data["checklist"]["materials_checked"]) + self.assertFalse(response.data["checklist"]["foreman_signed_off"]) + self.assertFalse(response.data["checklist"]["released"]) - def test_second_update_preserves_the_first(self) -> None: - update_completion_checklist( - self.job, {"time_entries_complete": True}, self.test_staff - ) - update_completion_checklist( - self.job, {"customer_approval_confirmed": True}, self.test_staff - ) + def test_every_item_can_be_ticked(self) -> None: + for field in CHECKLIST_FIELDS: + with self.subTest(field=field): + response = self._patch({field: True}) + self.assertEqual(response.status_code, 200) + self.assertTrue(response.data["checklist"][field]) + + def test_a_tick_can_be_withdrawn(self) -> None: + self._patch({"released": True}) + + response = self._patch({"released": False}) - checklist = get_completion_checklist(self.job) - self.assertTrue(checklist.time_entries_complete) - self.assertTrue(checklist.customer_approval_confirmed) + self.assertFalse(response.data["checklist"]["released"]) def test_unknown_item_is_rejected(self) -> None: - with self.assertRaises(ChecklistUpdateError) as ctx: - update_completion_checklist( - self.job, {"everything_is_fine": True}, self.test_staff - ) + response = self._patch({"everything_is_fine": True}) - self.assertIn("everything_is_fine", str(ctx.exception)) - self.assertFalse(JobCompletionChecklist.objects.filter(job=self.job).exists()) + self.assertEqual(response.status_code, 400) def test_non_boolean_value_is_rejected(self) -> None: - with self.assertRaises(ChecklistUpdateError): - update_completion_checklist( - self.job, - {"materials_complete": "yes"}, # type: ignore[dict-item] # the guard exists for untyped JSON off the wire - self.test_staff, - ) - - def test_rejected_update_does_not_apply_its_valid_items(self) -> None: + response = self._patch({"materials_checked": "yes"}) + + self.assertEqual(response.status_code, 400) + + def test_a_rejected_payload_applies_none_of_it(self) -> None: """An unknown key fails the whole payload rather than half-applying it.""" - with self.assertRaises(ChecklistUpdateError): - update_completion_checklist( - self.job, - {"materials_complete": True, "nonsense": True}, - self.test_staff, - ) - - self.assertFalse(get_completion_checklist(self.job).materials_complete) - - # --- Audit history --- - - def test_each_changed_item_adds_one_history_event(self) -> None: - update_completion_checklist( - self.job, - {"time_entries_complete": True, "materials_complete": True}, - self.test_staff, - ) + response = self._patch({"materials_checked": True, "nonsense": True}) - events = JobEvent.objects.filter( - job=self.job, event_type=CHECKLIST_UPDATED_EVENT - ) - self.assertEqual(events.count(), 2) + self.assertEqual(response.status_code, 400) + self.job.refresh_from_db() + self.assertFalse(self.job.materials_checked) - def test_history_event_records_item_values_and_staff(self) -> None: - update_completion_checklist( - self.job, {"customer_approval_confirmed": True}, self.test_staff - ) + # --- Audit --- - event = JobEvent.objects.get(job=self.job, event_type=CHECKLIST_UPDATED_EVENT) - change = event.detail["changes"][0] - self.assertEqual(change["field_name"], "Customer approval confirmed") - self.assertEqual(change["old_value"], "No") - self.assertEqual(change["new_value"], "Yes") - self.assertEqual(event.staff, self.test_staff) - self.assertIsNotNone(event.timestamp) - - def test_withdrawing_a_confirmation_is_audited(self) -> None: - """The change most worth finding later is someone unticking a box.""" - update_completion_checklist( - self.job, {"materials_complete": True}, self.test_staff - ) - update_completion_checklist( - self.job, {"materials_complete": False}, self.test_staff - ) + def test_each_changed_item_is_attributed_in_job_history(self) -> None: + self._patch({"foreman_signed_off": True}) + + event = JobEvent.objects.filter( + job=self.job, event_type=CHECKLIST_EVENT + ).latest("timestamp") + self.assertEqual(event.staff, self.office_staff) + self.assertEqual(event.description, "Foreman signed the job off") + + def test_withdrawing_a_tick_is_audited(self) -> None: + self._patch({"released": True}) + self._patch({"released": False}) events = JobEvent.objects.filter( - job=self.job, event_type=CHECKLIST_UPDATED_EVENT + job=self.job, event_type=CHECKLIST_EVENT ).order_by("timestamp") - self.assertEqual(events.count(), 2) self.assertEqual( - events[1].description, "Withdrew confirmation of all materials entered" + [e.description for e in events], ["Job released", "Job release withdrawn"] ) - def test_confirmation_reads_as_plain_english_in_history(self) -> None: - update_completion_checklist( - self.job, {"time_entries_complete": True}, self.test_staff - ) - - event = JobEvent.objects.get(job=self.job, event_type=CHECKLIST_UPDATED_EVENT) - self.assertEqual(event.description, "Confirmed all time entered") - - def test_setting_an_item_to_its_current_value_adds_no_event(self) -> None: - update_completion_checklist( - self.job, {"materials_complete": True}, self.test_staff - ) - update_completion_checklist( - self.job, {"materials_complete": True}, self.test_staff - ) + def test_reticking_the_same_value_adds_no_event(self) -> None: + self._patch({"materials_checked": True}) + self._patch({"materials_checked": True}) self.assertEqual( - JobEvent.objects.filter( - job=self.job, event_type=CHECKLIST_UPDATED_EVENT - ).count(), - 1, + JobEvent.objects.filter(job=self.job, event_type=CHECKLIST_EVENT).count(), 1 ) - # --- The checklist must not become a gate --- + # --- The checklist records, it does not gate --- - def test_checklist_does_not_change_job_status(self) -> None: + def test_ticking_everything_does_not_change_job_status(self) -> None: original_status = self.job.status - update_completion_checklist( - self.job, - { - "time_entries_complete": True, - "materials_complete": True, - "customer_approval_confirmed": True, - }, - self.test_staff, - ) + for field in CHECKLIST_FIELDS: + self._patch({field: True}) self.job.refresh_from_db() self.assertEqual(self.job.status, original_status) - def test_invoicing_works_with_an_untouched_checklist(self) -> None: - """Nothing confirmed must not stand between a customer and an invoice.""" + def test_an_untouched_checklist_does_not_block_invoicing(self) -> None: self._add_actual_revenue(Decimal("500")) result = calculate_invoice_amount(self.job, mode="invoice_costs_to_date") self.assertEqual(result.calculated_amount, Decimal("500")) - def test_invoice_amount_is_unchanged_by_confirmations(self) -> None: + def test_ticks_do_not_change_the_invoice_amount(self) -> None: self._add_actual_revenue(Decimal("500")) before = calculate_invoice_amount( self.job, mode="invoice_costs_to_date" ).calculated_amount - update_completion_checklist( - self.job, - {"time_entries_complete": True, "materials_complete": True}, - self.test_staff, - ) + self._patch({"timesheets_collected": True}) + self._patch({"materials_checked": True}) + self.job.refresh_from_db() after = calculate_invoice_amount( self.job, mode="invoice_costs_to_date" ).calculated_amount @@ -232,89 +183,3 @@ def _add_actual_revenue(self, revenue: Decimal) -> None: unit_rev=revenue, accounting_date=date.today(), ) - - -class TestFinishJobEndpoint(BaseAPITestCase): - """The generated client's read and partial-update operations.""" - - def setUp(self) -> None: - self.client_obj = Company.objects.create( - name="Test Company", - xero_last_modified=timezone.now(), - ) - self.job = Job( - company=self.client_obj, - name="Test Job", - pricing_methodology="time_materials", - ) - self.job.save(staff=self.test_staff) - self.url = reverse("jobs:job_finish_rest", args=[self.job.id]) - # Changing a checklist item is an office action; the shared test_staff is - # deliberately neither office nor workshop. - self.office_staff = Staff.objects.create_user( - email="office@example.com", - password="testpass", - first_name="Office", - last_name="Person", - is_office_staff=True, - ) - self.client.force_login(self.office_staff) - - def test_get_returns_summary_and_checklist(self) -> None: - response = self.client.get(self.url) - - self.assertEqual(response.status_code, 200) - self.assertIn("summary", response.data) - self.assertIn("checklist", response.data) - self.assertEqual(response.data["summary"]["basis"], "actual_revenue") - self.assertFalse(response.data["checklist"]["materials_complete"]) - self.assertIsNone(response.data["checklist"]["updated_by_name"]) - - def test_get_returns_currency_values_as_json_numbers(self) -> None: - """Zod on the frontend validates numbers; DRF's default strings fail it.""" - payload = self.client.get(self.url).json() - - for field, value in payload["summary"].items(): - if field == "basis": - continue - self.assertIsInstance(value, (int, float), msg=f"{field} is not a number") - - def test_patch_applies_a_partial_update_and_returns_fresh_state(self) -> None: - response = self.client.patch( - self.url, - data={"customer_approval_confirmed": True}, - content_type="application/json", - ) - - self.assertEqual(response.status_code, 200) - self.assertTrue(response.data["checklist"]["customer_approval_confirmed"]) - self.assertFalse(response.data["checklist"]["materials_complete"]) - self.assertEqual( - response.data["checklist"]["updated_by_name"], - self.office_staff.get_display_full_name(), - ) - - def test_get_on_a_fixed_price_job_reports_the_quote_basis(self) -> None: - """Exercises the quote prefetch branch under the n+1 middleware.""" - quoted_job = Job( - company=self.client_obj, - name="Quoted Job", - pricing_methodology="fixed_price", - ) - quoted_job.save(staff=self.test_staff) - - response = self.client.get( - reverse("jobs:job_finish_rest", args=[quoted_job.id]) - ) - - self.assertEqual(response.status_code, 200) - self.assertEqual(response.data["summary"]["basis"], "quote") - - def test_patch_rejects_an_unknown_item(self) -> None: - response = self.client.patch( - self.url, - data={"not_a_real_item": True}, - content_type="application/json", - ) - - self.assertEqual(response.status_code, 400) diff --git a/apps/job/tests/test_job_event_tracking.py b/apps/job/tests/test_job_event_tracking.py index 3103b29f8..d5591eabf 100644 --- a/apps/job/tests/test_job_event_tracking.py +++ b/apps/job/tests/test_job_event_tracking.py @@ -325,16 +325,36 @@ def test_friendly_boolean_paid(self) -> None: ) self.assertEqual(event.description, "Marked as paid") - def test_friendly_boolean_collected(self) -> None: + def test_friendly_checklist_confirmation(self) -> None: event = self._event( - "job_collected", + "completion_checklist_updated", { "changes": [ - {"field_name": "Collected", "old_value": "No", "new_value": "Yes"} + { + "field_name": "Foreman sign-off", + "old_value": "No", + "new_value": "Yes", + } + ] + }, + ) + self.assertEqual(event.description, "Foreman signed the job off") + + def test_friendly_checklist_withdrawal(self) -> None: + """Untickings are the changes worth finding later, so they read plainly.""" + event = self._event( + "completion_checklist_updated", + { + "changes": [ + { + "field_name": "Job released", + "old_value": "Yes", + "new_value": "No", + } ] }, ) - self.assertEqual(event.description, "Marked as collected") + self.assertEqual(event.description, "Job release withdrawn") def test_long_text_field_truncates(self) -> None: long_value = "x" * 200 diff --git a/apps/job/views/job_rest_views.py b/apps/job/views/job_rest_views.py index 94f3a7aa0..a399ce623 100644 --- a/apps/job/views/job_rest_views.py +++ b/apps/job/views/job_rest_views.py @@ -61,10 +61,6 @@ QuoteSerializer, WeeklyMetricsSerializer, ) -from apps.job.services.job_completion_checklist_service import ( - get_completion_checklist, - update_completion_checklist, -) from apps.job.services.job_rest_service import ( DeltaValidationError, JobRestService, @@ -1090,13 +1086,50 @@ def calculate_profit_margin(cost_set): return self.handle_service_error(e) +# The front-desk checklist items, as Job field names. The update endpoint derives +# its accepted keys from this, so adding an item here is the only change needed. +CHECKLIST_FIELDS = ( + "foreman_signed_off", + "timesheets_collected", + "materials_checked", + "customer_called", + "released", +) + + def _finish_job_payload(job: Job) -> FinishJobPayload: return { "summary": build_finish_job_summary(job), - "checklist": get_completion_checklist(job), + "checklist": job, } +def _apply_checklist_update(job: Job, updates: dict[str, bool], staff: Staff) -> None: + """Tick or untick checklist items, rejecting anything that is not one. + + Job.save() turns each changed field into a job-history event through + _FIELD_HANDLERS, so there is no audit code here to keep in step. + """ + unknown = sorted(set(updates) - set(CHECKLIST_FIELDS)) + if unknown: + raise ValueError( + f"Unknown checklist item(s): {', '.join(unknown)}. " + f"Valid items: {', '.join(CHECKLIST_FIELDS)}." + ) + + non_boolean = sorted( + key for key, value in updates.items() if not isinstance(value, bool) + ) + if non_boolean: + raise ValueError( + f"Checklist item(s) must be true or false: {', '.join(non_boolean)}." + ) + + for key, value in updates.items(): + setattr(job, key, value) + job.save(staff=staff) + + @method_decorator(csrf_exempt, name="dispatch") class JobFinishRestView(BaseJobRestView): """Finish Job workspace: the authoritative customer balance and checklist. @@ -1156,7 +1189,7 @@ def patch(self, request: Request, job_id: UUID) -> Response: ) job = get_job_for_finish_summary(job_id) - update_completion_checklist(job, self.parse_json_body(request), staff) + _apply_checklist_update(job, self.parse_json_body(request), staff) serializer = JobFinishResponseSerializer(_finish_job_payload(job)) return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/frontend/schema.yml b/frontend/schema.yml index 4a7b126a2..5414dd760 100644 --- a/frontend/schema.yml +++ b/frontend/schema.yml @@ -14330,36 +14330,32 @@ components: JobCompletionChecklist: type: object description: |- - Read shape for the Finish Job completion checklist. + Read shape for the front-desk completion checklist. - updated_at and updated_by_name are null until a staff member first changes an - item, including for the unsaved all-false checklist of a job nobody has - confirmed anything on. + The items are Job fields, so each tick is audited by the job's own + field-change machinery. Who ticked what, and when, is in the job history. properties: - time_entries_complete: + foreman_signed_off: type: boolean readOnly: true - materials_complete: + timesheets_collected: type: boolean readOnly: true - customer_approval_confirmed: + materials_checked: type: boolean readOnly: true - updated_at: - type: string - format: date-time + customer_called: + type: boolean readOnly: true - nullable: true - updated_by_name: - type: string - nullable: true + released: + type: boolean readOnly: true required: - - customer_approval_confirmed - - materials_complete - - time_entries_complete - - updated_at - - updated_by_name + - customer_called + - foreman_signed_off + - materials_checked + - released + - timesheets_collected JobCostSetSummary: type: object description: Serializer for cost set summary data in job views @@ -17822,14 +17818,18 @@ components: description: |- Partial update shape: send only the items being changed. - Every item is optional, and unknown keys are rejected by the service rather - than dropped, so a client typo is a 400 instead of a silent no-op. + Every item is optional, and unknown keys are rejected by the view rather than + dropped, so a client typo is a 400 instead of a silent no-op. properties: - time_entries_complete: + foreman_signed_off: + type: boolean + timesheets_collected: + type: boolean + materials_checked: type: boolean - materials_complete: + customer_called: type: boolean - customer_approval_confirmed: + released: type: boolean PatchedJobDeltaEnvelopeRequest: type: object diff --git a/frontend/src/api/generated/api.ts b/frontend/src/api/generated/api.ts index 526d3756b..cc5b15168 100644 --- a/frontend/src/api/generated/api.ts +++ b/frontend/src/api/generated/api.ts @@ -1800,11 +1800,11 @@ const FinishJobSummary = z.object({ over_invoiced_excl_gst: z.number().gt(-10000000000).lt(10000000000), }) const JobCompletionChecklist = z.object({ - time_entries_complete: z.boolean(), - materials_complete: z.boolean(), - customer_approval_confirmed: z.boolean(), - updated_at: z.string().datetime({ offset: true }).nullable(), - updated_by_name: z.string().nullable(), + foreman_signed_off: z.boolean(), + timesheets_collected: z.boolean(), + materials_checked: z.boolean(), + customer_called: z.boolean(), + released: z.boolean(), }) const JobFinishResponse = z.object({ summary: FinishJobSummary, @@ -1812,9 +1812,11 @@ const JobFinishResponse = z.object({ }) const PatchedJobCompletionChecklistUpdateRequest = z .object({ - time_entries_complete: z.boolean(), - materials_complete: z.boolean(), - customer_approval_confirmed: z.boolean(), + foreman_signed_off: z.boolean(), + timesheets_collected: z.boolean(), + materials_checked: z.boolean(), + customer_called: z.boolean(), + released: z.boolean(), }) .partial() const JobStatusEnum = z.enum([ diff --git a/frontend/src/components/job/JobFinishTab.vue b/frontend/src/components/job/JobFinishTab.vue index b4aed1eb1..2c56e171f 100644 --- a/frontend/src/components/job/JobFinishTab.vue +++ b/frontend/src/components/job/JobFinishTab.vue @@ -260,18 +260,15 @@

- Invoiced against the quote of - {{ formatCurrency(summary.job_value_excl_gst) }} (excl GST). + This is a Time & Materials job, so the time and materials on it are what the customer + pays. Get them right before invoicing.

-

- Last changed by {{ checklist.updated_by_name }} - on {{ formatDate(checklist.updated_at) }} -

+

Who ticked what is in the job history.

@@ -649,8 +646,7 @@ const log = debug('job:finish') type FinishJobSummary = z.infer type JobCompletionChecklist = z.infer -type ChecklistItemKey = - 'time_entries_complete' | 'materials_complete' | 'customer_approval_confirmed' +type ChecklistItemKey = keyof JobCompletionChecklist type Invoice = z.infer type XeroInvoiceCreateRequest = z.infer type JobCostSetSummaryOutput = z.infer @@ -694,11 +690,11 @@ const zeroSummary = (): FinishJobSummary => ({ const summary = reactive(zeroSummary()) const checklist = reactive({ - time_entries_complete: false, - materials_complete: false, - customer_approval_confirmed: false, - updated_at: null, - updated_by_name: null, + foreman_signed_off: false, + timesheets_collected: false, + materials_checked: false, + customer_called: false, + released: false, }) const invoices = ref>([]) @@ -811,18 +807,15 @@ const customAmountHint = computed(() => // --- Checklist --- -const checklistItems = computed>(() => { - // Time and material confirmations only mean something when the job is billed - // from what it consumed. - if (props.pricingMethodology === 'fixed_price') { - return [{ key: 'customer_approval_confirmed', label: 'Customer approval confirmed' }] - } - return [ - { key: 'time_entries_complete', label: 'All time entered' }, - { key: 'materials_complete', label: 'All materials entered' }, - { key: 'customer_approval_confirmed', label: 'Customer approval confirmed' }, - ] -}) +// The same questions on every job. Urgency differs between T&M and quoted work, +// but that is a note under the list, not a different list. +const checklistItems: Array<{ key: ChecklistItemKey; label: string }> = [ + { key: 'foreman_signed_off', label: 'Has the foreman signed off the job?' }, + { key: 'timesheets_collected', label: 'Have you collected the timesheet entries?' }, + { key: 'materials_checked', label: 'Have you checked the materials on the job?' }, + { key: 'customer_called', label: 'Have you called the customer?' }, + { key: 'released', label: 'Has the job been released?' }, +] // v-model has already applied the new value optimistically; this persists it and // puts it back if the server refuses, so a tick never survives a failed save. diff --git a/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts index 168b1cb22..2af2d8a05 100644 --- a/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts +++ b/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts @@ -55,11 +55,11 @@ const summary = (overrides: Record = {}) => ({ }) const checklist = () => ({ - time_entries_complete: false, - materials_complete: false, - customer_approval_confirmed: false, - updated_at: null, - updated_by_name: null, + foreman_signed_off: false, + timesheets_collected: false, + materials_checked: false, + customer_called: false, + released: false, }) const costSummary = () => ({ diff --git a/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts index 3250c024b..13e2e54dd 100644 --- a/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts +++ b/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts @@ -48,18 +48,26 @@ const summary = () => ({ over_invoiced_excl_gst: 0, }) -const checklist = (overrides: Record = {}) => ({ - time_entries_complete: false, - materials_complete: false, - customer_approval_confirmed: false, - updated_at: null, - updated_by_name: null, +const checklist = (overrides: Record = {}) => ({ + foreman_signed_off: false, + timesheets_collected: false, + materials_checked: false, + customer_called: false, + released: false, ...overrides, }) +const ITEMS = [ + 'foreman_signed_off', + 'timesheets_collected', + 'materials_checked', + 'customer_called', + 'released', +] + let mounted: ReturnType | null = null -function mountTab(pricingMethodology: string) { +function mountTab(pricingMethodology = 'fixed_price') { mounted = mount(JobFinishTab, { props: { jobId: 'job-1', pricingMethodology, jobStatus: 'in_progress' }, attachTo: document.body, @@ -88,110 +96,104 @@ describe('JobFinishTab completion checklist', () => { document.body.innerHTML = '' }) - it('asks a T&M job to confirm time, materials and customer approval', async () => { + it('asks the same five questions on a quoted job', async () => { + const wrapper = mountTab('fixed_price') + await flushPromises() + + for (const key of ITEMS) { + expect(item(wrapper, key).exists()).toBe(true) + } + }) + + it('asks the same five questions on a T&M job', async () => { const wrapper = mountTab('time_materials') await flushPromises() - expect(item(wrapper, 'time_entries_complete').exists()).toBe(true) - expect(item(wrapper, 'materials_complete').exists()).toBe(true) - expect(item(wrapper, 'customer_approval_confirmed').exists()).toBe(true) + for (const key of ITEMS) { + expect(item(wrapper, key).exists()).toBe(true) + } }) - it('asks a fixed-price job only for customer approval, and shows the quote basis', async () => { - const wrapper = mountTab('fixed_price') + it('warns that time and materials are what a T&M customer pays', async () => { + const wrapper = mountTab('time_materials') await flushPromises() - expect(item(wrapper, 'time_entries_complete').exists()).toBe(false) - expect(item(wrapper, 'materials_complete').exists()).toBe(false) - expect(item(wrapper, 'customer_approval_confirmed').exists()).toBe(true) - expect(wrapper.find('[data-automation-id="JobFinishTab-quote-basis"]').text()).toContain( - '1,000', + expect(wrapper.find('[data-automation-id="JobFinishTab-tm-urgency"]').text()).toContain( + 'before invoicing', ) }) - it('reflects confirmations already recorded on the job', async () => { + it('does not show the T&M urgency note on a quoted job', async () => { + const wrapper = mountTab('fixed_price') + await flushPromises() + + expect(wrapper.find('[data-automation-id="JobFinishTab-tm-urgency"]').exists()).toBe(false) + }) + + it('reflects ticks already recorded on the job', async () => { finishRetrieveMock.mockResolvedValue({ summary: summary(), - checklist: checklist({ materials_complete: true }), + checklist: checklist({ foreman_signed_off: true }), }) - const wrapper = mountTab('time_materials') + const wrapper = mountTab() await flushPromises() - expect((item(wrapper, 'materials_complete').element as HTMLInputElement).checked).toBe(true) - expect((item(wrapper, 'time_entries_complete').element as HTMLInputElement).checked).toBe(false) + expect((item(wrapper, 'foreman_signed_off').element as HTMLInputElement).checked).toBe(true) + expect((item(wrapper, 'released').element as HTMLInputElement).checked).toBe(false) }) it('sends only the item that changed', async () => { checklistUpdateMock.mockResolvedValue({ summary: summary(), - checklist: checklist({ materials_complete: true }), + checklist: checklist({ materials_checked: true }), }) - const wrapper = mountTab('time_materials') + const wrapper = mountTab() await flushPromises() - await item(wrapper, 'materials_complete').setValue(true) + await item(wrapper, 'materials_checked').setValue(true) await flushPromises() expect(checklistUpdateMock).toHaveBeenCalledWith( - { materials_complete: true }, + { materials_checked: true }, { params: { job_id: 'job-1' } }, ) }) - it('sends false when a confirmation is withdrawn', async () => { + it('sends false when a tick is withdrawn', async () => { finishRetrieveMock.mockResolvedValue({ summary: summary(), - checklist: checklist({ materials_complete: true }), + checklist: checklist({ released: true }), }) checklistUpdateMock.mockResolvedValue({ summary: summary(), checklist: checklist() }) - const wrapper = mountTab('time_materials') + const wrapper = mountTab() await flushPromises() - await item(wrapper, 'materials_complete').setValue(false) + await item(wrapper, 'released').setValue(false) await flushPromises() expect(checklistUpdateMock).toHaveBeenCalledWith( - { materials_complete: false }, + { released: false }, { params: { job_id: 'job-1' } }, ) }) it('reverts the box and warns the user when the save fails', async () => { checklistUpdateMock.mockRejectedValue(new Error('nope')) - const wrapper = mountTab('time_materials') + const wrapper = mountTab() await flushPromises() - await item(wrapper, 'materials_complete').setValue(true) + await item(wrapper, 'foreman_signed_off').setValue(true) await flushPromises() expect(toastErrorMock).toHaveBeenCalledWith('Failed to save checklist') - expect((item(wrapper, 'materials_complete').element as HTMLInputElement).checked).toBe(false) + expect((item(wrapper, 'foreman_signed_off').element as HTMLInputElement).checked).toBe(false) }) it('does not hide the invoice action behind the checklist', async () => { - const wrapper = mountTab('time_materials') + const wrapper = mountTab() await flushPromises() - expect((item(wrapper, 'customer_approval_confirmed').element as HTMLInputElement).checked).toBe( - false, - ) + expect((item(wrapper, 'foreman_signed_off').element as HTMLInputElement).checked).toBe(false) expect(wrapper.find('[data-automation-id="JobFinishTab-create-invoice"]').exists()).toBe(true) }) - - it('names who last changed a confirmation', async () => { - finishRetrieveMock.mockResolvedValue({ - summary: summary(), - checklist: checklist({ - customer_approval_confirmed: true, - updated_by_name: 'Office Person', - updated_at: '2026-08-01T09:00:00Z', - }), - }) - const wrapper = mountTab('time_materials') - await flushPromises() - - expect(wrapper.find('[data-automation-id="JobFinishTab-checklist"]').text()).toContain( - 'Office Person', - ) - }) }) diff --git a/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts index 54dde9b07..f7b1982da 100644 --- a/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts +++ b/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts @@ -46,11 +46,11 @@ const summary = () => ({ }) const checklist = () => ({ - time_entries_complete: false, - materials_complete: false, - customer_approval_confirmed: false, - updated_at: null, - updated_by_name: null, + foreman_signed_off: false, + timesheets_collected: false, + materials_checked: false, + customer_called: false, + released: false, }) let mounted: ReturnType | null = null diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 18d83a9e1..9d9ff1636 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -380,7 +380,6 @@ apps/job/models/job.py:0: error: Function is missing a type annotation for one o apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] -apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "BooleanField[bool | Combinable, bool]", variable has type "bool") [assignment] apps/job/models/job.py:0: error: Incompatible types in assignment (expression has type "DateTimeField[str | datetime | date | Combinable | None, datetime | None]", variable has type "datetime | None") [assignment] apps/job/models/job.py:0: error: Item "ForeignObjectRel" of "Field[Any, Any] | ForeignObjectRel" has no attribute "verbose_name" [union-attr] apps/job/models/job.py:0: error: Item "None" of "str | None" has no attribute "rstrip" [union-attr] From 1013c781cad59ebd0a00ce85a4f6e4d2cb3744b9 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Sat, 1 Aug 2026 18:01:17 +1200 Subject: [PATCH 37/39] refactor: derive job value in one place, stop the tab fabricating a balance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review found this PR re-implementing totals logic the app already had, and presenting invented figures as fact. Both are fixed by deletion. pricing_methodology was being branched on four times to answer one question — what is this job worth. calculate_invoice_amount dispatched on it and then the handlers asked again via two functions this PR had added; get_job_total_value had its own copy reading the summary["rev"] float mirror; and recalculate_job_invoicing_state had a fourth, which is how fully_invoiced could ignore a price cap the invoice itself respects. There is now one get_job_invoicing_basis and all of them call it, so a job cannot be reported at one value and invoiced at another. A test pins the agreement, and another pins the price cap the old reporting path dropped. Three more things existed already and were being duplicated: get_job_for_invoice_calculation (this PR had written a second loader), Invoice.amount_due (already serialized), and useJobFinancials.ts — a third copy of the same sum in the browser, which counted VOIDED invoices and ignored the price cap, so the Rejected-Job warning disagreed with what the job would actually be invoiced for. It is deleted and that warning now reads the server's figure. The basis field went too: it was pricing_methodology with the values relabelled, returned by the API and never read. On the frontend, loadAll's catch cleared `loading` while leaving a fabricated zero summary on screen, so a failed request rendered "Total to pay $0.00 — Nothing left to pay. This job is fully invoiced and settled." There is no placeholder now; a failed load says so and shows no figures. Tested. Job.DoesNotExist was re-raised as ValueError inside an except clause, which a sibling clause cannot catch, so every job view answered 500 for a missing job. http_status_for_exception already maps it to 404, so the clauses are deleted across the file and a test covers it. Structurally: the invoice card moves to JobInvoiceCard.vue and the checklist items are declared once as Job.COMPLETION_CHECKLIST_FIELDS, which both serializers derive from. JobFinishTab is now recognisably a rename of JobCostAnalysisTab rather than a rewrite of it. KAN-323 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01ACLSprAHJSeQErMxQqLKDH --- apps/accounting/services/__init__.py | 10 +- .../accounting/services/finish_job_summary.py | 56 +- .../services/invoice_calculation.py | 93 +- .../tests/test_finish_job_summary.py | 293 ++--- .../accounts/tests/test_auth_observability.py | 16 +- apps/job/models/job.py | 11 + apps/job/serializers/job_serializer.py | 35 +- apps/job/services/__init__.py | 2 + apps/job/services/job_service.py | 88 +- apps/job/tests/test_completion_checklist.py | 34 +- apps/job/tests/test_mcp_tool_integration.py | 26 - apps/job/views/job_rest_views.py | 82 +- .../tests/test_access_logging_middleware.py | 5 +- apps/workflow/tests/test_backup_scripts.py | 18 - frontend/schema.yml | 12 +- frontend/src/api/generated/api.ts | 1 - frontend/src/components/job/JobFinishTab.vue | 1027 +++++------------ .../src/components/job/JobInvoiceCard.vue | 459 ++++++++ frontend/src/components/job/JobViewTabs.vue | 4 - .../__tests__/JobFinishTab.balance.test.ts | 85 +- .../__tests__/JobFinishTab.checklist.test.ts | 85 +- .../JobFinishTab.labourHours.test.ts | 154 +-- .../job/__tests__/finishTabFixtures.ts | 89 ++ frontend/src/composables/useJobFinancials.ts | 68 -- frontend/src/pages/jobs/[id]/(index).vue | 14 +- mypy-baseline.txt | 1 - 26 files changed, 1231 insertions(+), 1537 deletions(-) create mode 100644 frontend/src/components/job/JobInvoiceCard.vue create mode 100644 frontend/src/components/job/__tests__/finishTabFixtures.ts delete mode 100644 frontend/src/composables/useJobFinancials.ts diff --git a/apps/accounting/services/__init__.py b/apps/accounting/services/__init__.py index c983eb20c..910d6dedc 100644 --- a/apps/accounting/services/__init__.py +++ b/apps/accounting/services/__init__.py @@ -9,16 +9,15 @@ from .finish_job_summary import ( FinishJobSummary, build_finish_job_summary, - get_job_for_finish_summary, get_outstanding_invoiced_incl_tax, ) from .invoice_calculation import ( InvoiceCalculationError, InvoiceCalculationResult, + JobInvoicingBasis, calculate_invoice_amount, get_job_for_invoice_calculation, - get_job_value_basis, - get_job_value_excl_tax, + get_job_invoicing_basis, get_prior_valid_invoice_total, ) from .payroll_reconciliation_service import PayrollReconciliationService @@ -34,6 +33,7 @@ "InvoiceCalculationError", "InvoiceCalculationResult", "JobAgingService", + "JobInvoicingBasis", "KPIService", "PayrollReconciliationService", "RDTISpendService", @@ -42,10 +42,8 @@ "WIPService", "build_finish_job_summary", "calculate_invoice_amount", - "get_job_for_finish_summary", "get_job_for_invoice_calculation", - "get_job_value_basis", - "get_job_value_excl_tax", + "get_job_invoicing_basis", "get_outstanding_invoiced_incl_tax", "get_prior_valid_invoice_total", ] diff --git a/apps/accounting/services/finish_job_summary.py b/apps/accounting/services/finish_job_summary.py index ed0fc12a1..959f3948d 100644 --- a/apps/accounting/services/finish_job_summary.py +++ b/apps/accounting/services/finish_job_summary.py @@ -1,27 +1,25 @@ """Authoritative customer balance for the Finish Job workspace. Answers the counter question — what does this customer need to pay, including -tax — as a single set of decimal currency values. Every figure is computed here -so the frontend only formats what it is given (ADR 0020). +tax — as decimal currency values, so the frontend only formats what it is given +(ADR 0020). -The job value, price-cap behaviour and valid-invoice statuses come from -``invoice_calculation``; this module adds only the tax and outstanding-balance -arithmetic on top of them, so a change to the invoicing basis moves both the -invoice a user can create and the balance they are shown. +Adds nothing but the tax and outstanding-balance arithmetic: the job's value, its +price cap and the valid-invoice statuses all come from ``invoice_calculation``, +so the amount a user can invoice and the amount they are shown cannot drift +apart. """ from dataclasses import dataclass from decimal import ROUND_HALF_UP, Decimal -from uuid import UUID -from django.db.models import Sum, prefetch_related_objects +from django.db.models import Sum from django.db.models.functions import Coalesce from apps.accounting.models.invoice import Invoice from apps.accounting.services.invoice_calculation import ( INVOICE_VALID_STATUSES, - get_job_value_basis, - get_job_value_excl_tax, + get_job_invoicing_basis, get_prior_valid_invoice_total, ) from apps.job.models import Job @@ -32,14 +30,8 @@ @dataclass(frozen=True) class FinishJobSummary: - """Every currency value the Finish Job workspace displays. + """Every currency value the Finish Job workspace displays.""" - ``basis`` names the cost set the job value is measured against ("quote" for - fixed-price work, "actual_revenue" for T&M) so the UI can label the figure - without inferring it from the pricing methodology. - """ - - basis: str job_value_excl_gst: Decimal valid_invoiced_excl_gst: Decimal outstanding_invoiced_incl_gst: Decimal @@ -59,27 +51,12 @@ def get_outstanding_invoiced_incl_tax(job: Job) -> Decimal: ) -def get_job_for_finish_summary(job_id: UUID) -> Job: - """Load a job with the cost set its value is measured against. - - Only the basis cost set is loaded, and its cost lines are prefetched because - the job value sums them. Fetching both cost sets would eagerly load one the - summary never reads; fetching neither would cost a query per cost line. - """ - job = Job.objects.get(id=job_id) - - if job.pricing_methodology == "fixed_price": - prefetch_related_objects([job], "latest_quote__cost_lines") - else: - prefetch_related_objects([job], "latest_actual__cost_lines") - - return job - - def build_finish_job_summary(job: Job) -> FinishJobSummary: - job_value = _as_currency(get_job_value_excl_tax(job)) - invoiced = _as_currency(get_prior_valid_invoice_total(job)) - outstanding = _as_currency(get_outstanding_invoiced_incl_tax(job)) + job_value = get_job_invoicing_basis(job).target_total.quantize( + CENT, rounding=ROUND_HALF_UP + ) + invoiced = get_prior_valid_invoice_total(job) + outstanding = get_outstanding_invoiced_incl_tax(job) # A job invoiced beyond its value has nothing left to invoice; the excess is # reported separately for resolution in Xero rather than netted off, which @@ -92,7 +69,6 @@ def build_finish_job_summary(job: Job) -> FinishJobSummary: remaining_incl = remaining_excl + remaining_gst return FinishJobSummary( - basis=get_job_value_basis(job), job_value_excl_gst=job_value, valid_invoiced_excl_gst=invoiced, outstanding_invoiced_incl_gst=outstanding, @@ -102,7 +78,3 @@ def build_finish_job_summary(job: Job) -> FinishJobSummary: total_to_pay_incl_gst=outstanding + remaining_incl, over_invoiced_excl_gst=over_invoiced, ) - - -def _as_currency(amount: Decimal) -> Decimal: - return amount.quantize(CENT, rounding=ROUND_HALF_UP) diff --git a/apps/accounting/services/invoice_calculation.py b/apps/accounting/services/invoice_calculation.py index 911a1f2e1..44e9320a8 100644 --- a/apps/accounting/services/invoice_calculation.py +++ b/apps/accounting/services/invoice_calculation.py @@ -31,38 +31,36 @@ class InvoiceCalculationResult: calculated_amount: Decimal = Decimal("0") -def get_job_value_basis(job: Job) -> str: - """Name of the cost set a job's complete value is measured against.""" - if job.pricing_methodology == "fixed_price": - return "quote" - else: - return "actual_revenue" +@dataclass(frozen=True) +class JobInvoicingBasis: + """What a job is worth excluding tax, and which cost set says so.""" + basis: str + target_total: Decimal -def get_job_value_excl_tax(job: Job) -> Decimal: - """The complete value of a job excluding tax, on its own pricing basis. - Fixed-price work is worth its quote; T&M work is worth its actual revenue, - limited by the price cap when one is set. A job whose basis cost set does not - exist yet is worth nothing — it has not been quoted, and no work has been - recorded against it. Invoicing such a job is a separate question, guarded by - the calculation paths below. +def get_job_invoicing_basis(job: Job) -> JobInvoicingBasis: + """The complete value of a job excluding tax. + + The single place a job's value is derived: fixed-price work is worth its + quote, T&M work its actual revenue limited by any price cap. Everything that + needs a job's value — invoice calculation, the Finish Job balance, + ``job_service.get_job_total_value`` — reads it from here, so the three cannot + disagree about what a job is worth. """ if job.pricing_methodology == "fixed_price": - quote = job.latest_quote - if not quote: - return Decimal("0") - return Decimal(str(quote.total_revenue)) - - actual = job.latest_actual - if not actual: - return Decimal("0") - - target_total = Decimal(str(actual.total_revenue)) - if job.price_cap is not None: - return min(target_total, Decimal(str(job.price_cap))) - else: - return target_total + return JobInvoicingBasis( + basis="quote", target_total=Decimal(str(job.latest_quote.total_revenue)) + ) + + actual_revenue = Decimal(str(job.latest_actual.total_revenue)) + if job.price_cap is None: + return JobInvoicingBasis(basis="actual_revenue", target_total=actual_revenue) + + return JobInvoicingBasis( + basis="actual_revenue", + target_total=min(actual_revenue, Decimal(str(job.price_cap))), + ) def get_prior_valid_invoice_total(job: Job) -> Decimal: @@ -74,9 +72,13 @@ def get_prior_valid_invoice_total(job: Job) -> Decimal: def get_job_for_invoice_calculation(job_id: UUID) -> Job: - job = Job.objects.select_related("company", "latest_quote", "latest_actual").get( - id=job_id - ) + """Load a job with the cost set its value is measured against. + + Only the basis cost set is fetched: loading both eagerly pulls one that is + never read, which the n+1 guard reports. Its cost lines are prefetched + because ``total_revenue`` sums them. + """ + job = Job.objects.select_related("company").get(id=job_id) if job.pricing_methodology == "fixed_price": prefetch_related_objects([job], "latest_quote__cost_lines") @@ -93,26 +95,26 @@ def calculate_invoice_amount( amount: Decimal | None = None, ) -> InvoiceCalculationResult: prior_invoiced = get_prior_valid_invoice_total(job) + job_basis = get_job_invoicing_basis(job) + # Which modes are legal is a different question from what the job is worth, + # so it keeps its own branch; the handlers below are given the value. if job.pricing_methodology == "fixed_price": - return _calculate_fixed_price(job, mode, prior_invoiced, percent, amount) + return _calculate_fixed_price(job_basis, mode, prior_invoiced, percent, amount) else: - return _calculate_time_materials(job, mode, prior_invoiced, percent, amount) + return _calculate_time_materials( + job_basis, mode, prior_invoiced, percent, amount + ) def _calculate_fixed_price( - job: Job, + job_basis: JobInvoicingBasis, mode: str, prior_invoiced: Decimal, percent: Decimal | None, amount: Decimal | None, ) -> InvoiceCalculationResult: - if not job.latest_quote: - raise InvoiceCalculationError( - "Fixed-price job has no quote to invoice against." - ) - target_total = get_job_value_excl_tax(job) - target_basis = get_job_value_basis(job) + target_total = job_basis.target_total if mode == "invoice_full": calculated = target_total - prior_invoiced @@ -141,7 +143,7 @@ def _calculate_fixed_price( return InvoiceCalculationResult( mode=mode, - target_basis=target_basis, + target_basis=job_basis.basis, target_total=target_total, prior_invoiced_total=prior_invoiced, requested_percent=percent, @@ -151,18 +153,13 @@ def _calculate_fixed_price( def _calculate_time_materials( - job: Job, + job_basis: JobInvoicingBasis, mode: str, prior_invoiced: Decimal, percent: Decimal | None, amount: Decimal | None, ) -> InvoiceCalculationResult: - if not job.latest_actual: - raise InvoiceCalculationError( - "T&M job has no actual cost set to invoice against." - ) - target_total = get_job_value_excl_tax(job) - target_basis = get_job_value_basis(job) + target_total = job_basis.target_total if mode == "invoice_costs_to_date": calculated = target_total - prior_invoiced @@ -186,7 +183,7 @@ def _calculate_time_materials( return InvoiceCalculationResult( mode=mode, - target_basis=target_basis, + target_basis=job_basis.basis, target_total=target_total, prior_invoiced_total=prior_invoiced, requested_percent=percent, diff --git a/apps/accounting/tests/test_finish_job_summary.py b/apps/accounting/tests/test_finish_job_summary.py index 24c960345..25667f442 100644 --- a/apps/accounting/tests/test_finish_job_summary.py +++ b/apps/accounting/tests/test_finish_job_summary.py @@ -1,25 +1,22 @@ -"""Tests for the Finish Job customer balance summary. +"""Tests for the Finish Job customer balance. -Each test names a counter situation from KAN-323: what the customer must pay, -including GST, given what has already been invoiced and paid. +The counter situations from KAN-323 are all the same arithmetic over different +invoice states, so they are one table. The cases that are not just arithmetic — +the price cap, excluded statuses, over-invoicing and GST rounding — get their own +tests. """ import uuid from datetime import date from decimal import Decimal -from django.db import connection -from django.test.utils import CaptureQueriesContext from django.utils import timezone from apps.accounting.models.invoice import Invoice -from apps.accounting.services.finish_job_summary import ( - build_finish_job_summary, - get_job_for_finish_summary, -) +from apps.accounting.services.finish_job_summary import build_finish_job_summary from apps.company.models import Company from apps.job.models import Job -from apps.job.models.costing import CostLine, CostSet +from apps.job.models.costing import CostSet from apps.testing import BaseTestCase from apps.workflow.models import CompanyDefaults @@ -34,16 +31,24 @@ def setUp(self) -> None: defaults.gst_rate = Decimal("0.1500") defaults.save() - def _create_job(self, pricing_methodology: str = "time_materials") -> Job: + def _job(self, pricing_methodology: str, revenue: Decimal) -> Job: job = Job( company=self.client_obj, name="Test Job", pricing_methodology=pricing_methodology, ) job.save(staff=self.test_staff) + basis = ( + job.latest_quote + if pricing_methodology == "fixed_price" + else job.latest_actual + ) + self._add_revenue_line(basis, revenue) return job def _add_revenue_line(self, cost_set: CostSet, revenue: Decimal) -> None: + from apps.job.models.costing import CostLine + CostLine.objects.create( cost_set=cost_set, kind="adjust", @@ -54,7 +59,7 @@ def _add_revenue_line(self, cost_set: CostSet, revenue: Decimal) -> None: accounting_date=date.today(), ) - def _create_invoice( + def _invoice( self, job: Job, amount: Decimal, @@ -76,29 +81,50 @@ def _create_invoice( raw_json={}, ) - # --- Job value basis --- - - def test_fixed_price_value_is_the_quote(self) -> None: - job = self._create_job("fixed_price") - self._add_revenue_line(job.latest_quote, Decimal("5000")) - - summary = build_finish_job_summary(job) - - self.assertEqual(summary.basis, "quote") - self.assertEqual(summary.job_value_excl_gst, Decimal("5000.00")) - - def test_time_materials_value_is_actual_revenue(self) -> None: - job = self._create_job("time_materials") - self._add_revenue_line(job.latest_actual, Decimal("1234.56")) - - summary = build_finish_job_summary(job) - - self.assertEqual(summary.basis, "actual_revenue") - self.assertEqual(summary.job_value_excl_gst, Decimal("1234.56")) + def test_counter_situations(self) -> None: + """Every KAN-323 acceptance scenario, on a $1000 fixed-price job.""" + cases = [ + # label, invoices as (excl_tax, amount_due, status), expected total to pay + ("nothing invoiced", [], Decimal("1150.00")), + ( + "paid in advance", + [(Decimal("1000"), Decimal("0.00"), "PAID")], + Decimal("0.00"), + ), + ( + "unpaid advance invoice", + [(Decimal("1000"), Decimal("1150.00"), "AUTHORISED")], + Decimal("1150.00"), + ), + ( + "paid deposit, balance uninvoiced", + [(Decimal("400"), Decimal("0.00"), "PAID")], + Decimal("690.00"), + ), + ( + "unpaid progress invoice plus uninvoiced balance", + [(Decimal("400"), Decimal("460.00"), "AUTHORISED")], + Decimal("1150.00"), + ), + ( + "partly paid invoice", + [(Decimal("1000"), Decimal("150.00"), "AUTHORISED")], + Decimal("150.00"), + ), + ] + + for label, invoices, expected in cases: + with self.subTest(label): + job = self._job("fixed_price", Decimal("1000")) + for amount, due, status in invoices: + self._invoice(job, amount, amount_due=due, status=status) + + summary = build_finish_job_summary(job) + + self.assertEqual(summary.total_to_pay_incl_gst, expected) def test_time_materials_value_is_limited_by_price_cap(self) -> None: - job = self._create_job("time_materials") - self._add_revenue_line(job.latest_actual, Decimal("5000")) + job = self._job("time_materials", Decimal("5000")) job.price_cap = Decimal("3000.00") job.save(staff=self.test_staff) @@ -107,173 +133,102 @@ def test_time_materials_value_is_limited_by_price_cap(self) -> None: self.assertEqual(summary.job_value_excl_gst, Decimal("3000.00")) self.assertEqual(summary.remaining_to_invoice_excl_gst, Decimal("3000.00")) - def test_fixed_price_without_a_quote_is_worth_nothing_yet(self) -> None: - """A job created but not yet quoted must still render a balance.""" - job = self._create_job("fixed_price") - - summary = build_finish_job_summary(job) - - self.assertEqual(summary.job_value_excl_gst, Decimal("0.00")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("0.00")) - - # --- Counter situations --- - - def test_nothing_invoiced_charges_the_whole_job_plus_gst(self) -> None: - job = self._create_job("fixed_price") - self._add_revenue_line(job.latest_quote, Decimal("1000")) + def test_voided_and_deleted_invoices_do_not_count(self) -> None: + job = self._job("fixed_price", Decimal("1000")) + self._invoice(job, Decimal("1000"), Decimal("1150.00"), "VOIDED") + self._invoice(job, Decimal("1000"), Decimal("1150.00"), "DELETED") summary = build_finish_job_summary(job) self.assertEqual(summary.valid_invoiced_excl_gst, Decimal("0.00")) - self.assertEqual(summary.remaining_to_invoice_excl_gst, Decimal("1000.00")) - self.assertEqual(summary.remaining_gst, Decimal("150.00")) - self.assertEqual(summary.remaining_to_invoice_incl_gst, Decimal("1150.00")) + self.assertEqual(summary.outstanding_invoiced_incl_gst, Decimal("0.00")) self.assertEqual(summary.total_to_pay_incl_gst, Decimal("1150.00")) - def test_paid_advance_invoice_leaves_nothing_to_pay(self) -> None: - """Invoiced in full before work started, and the customer has paid.""" - job = self._create_job("fixed_price") - self._add_revenue_line(job.latest_quote, Decimal("1000")) - self._create_invoice( - job, Decimal("1000"), amount_due=Decimal("0.00"), status="PAID" - ) + def test_over_invoicing_is_reported_without_a_negative_remainder(self) -> None: + """T&M actuals can land below what was already invoiced.""" + job = self._job("time_materials", Decimal("800")) + self._invoice(job, Decimal("1000"), Decimal("0.00"), "PAID") summary = build_finish_job_summary(job) + self.assertEqual(summary.over_invoiced_excl_gst, Decimal("200.00")) self.assertEqual(summary.remaining_to_invoice_excl_gst, Decimal("0.00")) - self.assertEqual(summary.remaining_gst, Decimal("0.00")) self.assertEqual(summary.total_to_pay_incl_gst, Decimal("0.00")) - self.assertEqual(summary.over_invoiced_excl_gst, Decimal("0.00")) - def test_unpaid_advance_invoice_is_the_amount_to_pay(self) -> None: - job = self._create_job("fixed_price") - self._add_revenue_line(job.latest_quote, Decimal("1000")) - self._create_invoice(job, Decimal("1000"), amount_due=Decimal("1150.00")) + def test_gst_rounds_to_the_nearest_cent(self) -> None: + """$333.33 x 15% = $49.9995, which must present as $50.00.""" + job = self._job("time_materials", Decimal("333.33")) summary = build_finish_job_summary(job) - self.assertEqual(summary.remaining_to_invoice_excl_gst, Decimal("0.00")) - self.assertEqual(summary.outstanding_invoiced_incl_gst, Decimal("1150.00")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("1150.00")) + self.assertEqual(summary.remaining_gst, Decimal("50.00")) + self.assertEqual(summary.total_to_pay_incl_gst, Decimal("383.33")) - def test_paid_deposit_leaves_only_the_uninvoiced_balance(self) -> None: - job = self._create_job("fixed_price") - self._add_revenue_line(job.latest_quote, Decimal("1000")) - self._create_invoice( - job, Decimal("400"), amount_due=Decimal("0.00"), status="PAID" - ) + def test_gst_uses_the_configured_rate(self) -> None: + defaults = CompanyDefaults.get_solo() + defaults.gst_rate = Decimal("0.1250") + defaults.save() + job = self._job("time_materials", Decimal("1000")) summary = build_finish_job_summary(job) - self.assertEqual(summary.outstanding_invoiced_incl_gst, Decimal("0.00")) - self.assertEqual(summary.remaining_to_invoice_excl_gst, Decimal("600.00")) - self.assertEqual(summary.remaining_gst, Decimal("90.00")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("690.00")) - - def test_unpaid_progress_invoice_and_balance_are_both_owed(self) -> None: - job = self._create_job("fixed_price") - self._add_revenue_line(job.latest_quote, Decimal("1000")) - self._create_invoice(job, Decimal("400"), amount_due=Decimal("460.00")) + self.assertEqual(summary.remaining_gst, Decimal("125.00")) + self.assertEqual(summary.total_to_pay_incl_gst, Decimal("1125.00")) - summary = build_finish_job_summary(job) - self.assertEqual(summary.outstanding_invoiced_incl_gst, Decimal("460.00")) - self.assertEqual(summary.remaining_to_invoice_incl_gst, Decimal("690.00")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("1150.00")) +class TestJobValueIsSharedWithReporting(BaseTestCase): + """get_job_total_value must agree with the invoicing basis. - def test_partly_paid_invoice_owes_only_its_outstanding_balance(self) -> None: - job = self._create_job("fixed_price") - self._add_revenue_line(job.latest_quote, Decimal("1000")) - self._create_invoice(job, Decimal("1000"), amount_due=Decimal("150.00")) + It used to read CostSet.summary["rev"], a float mirror maintained by + CostLine._update_cost_set_summary, while invoicing read total_revenue. Both + now come from get_job_invoicing_basis, so a job cannot be reported at one + value and invoiced at another. + """ - summary = build_finish_job_summary(job) - - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("150.00")) + def setUp(self) -> None: + self.client_obj = Company.objects.create( + name="Test Company", + xero_last_modified=timezone.now(), + ) - # --- Excluded invoices --- + def _job_with_revenue(self, revenue: Decimal) -> Job: + from apps.job.models.costing import CostLine - def test_voided_and_deleted_invoices_do_not_count(self) -> None: - job = self._create_job("fixed_price") - self._add_revenue_line(job.latest_quote, Decimal("1000")) - self._create_invoice( - job, Decimal("1000"), amount_due=Decimal("1150.00"), status="VOIDED" + job = Job( + company=self.client_obj, + name="Test Job", + pricing_methodology="time_materials", ) - self._create_invoice( - job, Decimal("1000"), amount_due=Decimal("1150.00"), status="DELETED" + job.save(staff=self.test_staff) + CostLine.objects.create( + cost_set=job.latest_actual, + kind="adjust", + desc="Test line", + quantity=Decimal("1.000"), + unit_cost=Decimal("0.00"), + unit_rev=revenue, + accounting_date=date.today(), ) + return job - summary = build_finish_job_summary(job) - - self.assertEqual(summary.valid_invoiced_excl_gst, Decimal("0.00")) - self.assertEqual(summary.outstanding_invoiced_incl_gst, Decimal("0.00")) - self.assertEqual(summary.remaining_to_invoice_excl_gst, Decimal("1000.00")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("1150.00")) - - # --- Over-invoicing --- - - def test_over_invoicing_is_reported_without_a_negative_remainder(self) -> None: - """T&M actuals can fall below what was already invoiced.""" - job = self._create_job("time_materials") - self._add_revenue_line(job.latest_actual, Decimal("800")) - self._create_invoice( - job, Decimal("1000"), amount_due=Decimal("0.00"), status="PAID" + def test_reported_value_matches_the_invoicing_basis(self) -> None: + from apps.accounting.services.invoice_calculation import ( + get_job_invoicing_basis, ) + from apps.job.services.job_service import get_job_total_value - summary = build_finish_job_summary(job) - - self.assertEqual(summary.over_invoiced_excl_gst, Decimal("200.00")) - self.assertEqual(summary.remaining_to_invoice_excl_gst, Decimal("0.00")) - self.assertEqual(summary.remaining_gst, Decimal("0.00")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("0.00")) - - def test_over_invoiced_and_unpaid_still_owes_the_invoice(self) -> None: - job = self._create_job("time_materials") - self._add_revenue_line(job.latest_actual, Decimal("800")) - self._create_invoice(job, Decimal("1000"), amount_due=Decimal("1150.00")) - - summary = build_finish_job_summary(job) - - self.assertEqual(summary.over_invoiced_excl_gst, Decimal("200.00")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("1150.00")) - - # --- GST arithmetic --- - - def test_gst_rounds_to_the_nearest_cent(self) -> None: - """$333.33 x 15% = $49.9995, which must present as $50.00.""" - job = self._create_job("time_materials") - self._add_revenue_line(job.latest_actual, Decimal("333.33")) - - summary = build_finish_job_summary(job) - - self.assertEqual(summary.remaining_gst, Decimal("50.00")) - self.assertEqual(summary.remaining_to_invoice_incl_gst, Decimal("383.33")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("383.33")) - - def test_summary_query_count_does_not_grow_with_cost_lines(self) -> None: - """The job value sums cost lines, so the basis cost set must be prefetched.""" - job = self._create_job("time_materials") - for _ in range(10): - self._add_revenue_line(job.latest_actual, Decimal("10")) - - with CaptureQueriesContext(connection) as few_lines: - build_finish_job_summary(get_job_for_finish_summary(job.id)) + job = self._job_with_revenue(Decimal("1234.56")) - for _ in range(20): - self._add_revenue_line(job.latest_actual, Decimal("10")) - - with CaptureQueriesContext(connection) as many_lines: - build_finish_job_summary(get_job_for_finish_summary(job.id)) - - self.assertEqual(len(many_lines), len(few_lines)) + self.assertEqual( + get_job_total_value(job), get_job_invoicing_basis(job).target_total + ) - def test_gst_uses_the_configured_rate(self) -> None: - defaults = CompanyDefaults.get_solo() - defaults.gst_rate = Decimal("0.1250") - defaults.save() - job = self._create_job("time_materials") - self._add_revenue_line(job.latest_actual, Decimal("1000")) + def test_reported_value_respects_the_price_cap(self) -> None: + """The old implementation ignored price_cap and over-reported.""" + from apps.job.services.job_service import get_job_total_value - summary = build_finish_job_summary(job) + job = self._job_with_revenue(Decimal("5000")) + job.price_cap = Decimal("3000.00") + job.save(staff=self.test_staff) - self.assertEqual(summary.remaining_gst, Decimal("125.00")) - self.assertEqual(summary.total_to_pay_incl_gst, Decimal("1125.00")) + self.assertEqual(get_job_total_value(job), Decimal("3000.00")) diff --git a/apps/accounts/tests/test_auth_observability.py b/apps/accounts/tests/test_auth_observability.py index d82cef775..f08932e74 100644 --- a/apps/accounts/tests/test_auth_observability.py +++ b/apps/accounts/tests/test_auth_observability.py @@ -26,15 +26,16 @@ def test_jwt_auth_logs_cookie_miss_with_request_context() -> None: with patch.object(authentication.logger, "info") as log_info: assert JWTAuthentication().authenticate(request) is None - log_info.assert_called_once_with( - "JWT AUTH MISS - method=%s path=%s ip=%s access_cookie=%s access_cookie_present=%s refresh_cookie_present=%s", + log_info.assert_called_once() + _, *log_args = log_info.call_args.args + assert log_args == [ "GET", "/api/accounts/me/", TEST_CLIENT_IP, "access_token", False, False, - ) + ] @override_settings(ENABLE_JWT_AUTH=True) @@ -111,12 +112,9 @@ def test_logout_logs_cookie_presence_without_token_values() -> None: response = LogoutUserAPIView.as_view()(request) assert response.status_code == 200 - log_info.assert_called_once_with( - "JWT LOGOUT REQUEST - ip=%s access_cookie_present=%s refresh_cookie_present=%s", - TEST_CLIENT_IP, - True, - True, - ) + log_info.assert_called_once() + _, *log_args = log_info.call_args.args + assert log_args == [TEST_CLIENT_IP, True, True] @pytest.mark.django_db diff --git a/apps/job/models/job.py b/apps/job/models/job.py index 676cc5f3a..aff619284 100644 --- a/apps/job/models/job.py +++ b/apps/job/models/job.py @@ -154,6 +154,17 @@ class Job(models.Model): "is_urgent", ] + # The front-desk completion checklist, in display order. The Finish Job + # serializers derive their field lists from this, so an item is declared + # once. + COMPLETION_CHECKLIST_FIELDS = [ + "foreman_signed_off", + "timesheets_collected", + "materials_checked", + "customer_called", + "released", + ] + # Fields where changes are NOT audited via JobEvent. Every field NOT in # this set is automatically tracked — adding a new business field to Job # gives you audit coverage for free. diff --git a/apps/job/serializers/job_serializer.py b/apps/job/serializers/job_serializer.py index 9713f08cd..e6ef86c9b 100644 --- a/apps/job/serializers/job_serializer.py +++ b/apps/job/serializers/job_serializer.py @@ -863,7 +863,6 @@ class FinishJobSummarySerializer(serializers.Serializer[FinishJobSummary]): than recomputes them (ADR 0020). """ - basis = serializers.CharField(read_only=True) job_value_excl_gst = serializers.DecimalField( max_digits=12, decimal_places=2, read_only=True ) @@ -890,32 +889,38 @@ class FinishJobSummarySerializer(serializers.Serializer[FinishJobSummary]): ) -class JobCompletionChecklistSerializer(serializers.Serializer[Job]): +class JobCompletionChecklistSerializer(NullUnsetModelSerializer[Job]): """Read shape for the front-desk completion checklist. The items are Job fields, so each tick is audited by the job's own field-change machinery. Who ticked what, and when, is in the job history. """ - foreman_signed_off = serializers.BooleanField(read_only=True) - timesheets_collected = serializers.BooleanField(read_only=True) - materials_checked = serializers.BooleanField(read_only=True) - customer_called = serializers.BooleanField(read_only=True) - released = serializers.BooleanField(read_only=True) + class Meta: + model = Job + fields = Job.COMPLETION_CHECKLIST_FIELDS + read_only_fields = fields -class JobCompletionChecklistUpdateSerializer(serializers.Serializer[None]): +class JobCompletionChecklistUpdateSerializer(NullUnsetModelSerializer[Job]): """Partial update shape: send only the items being changed. - Every item is optional, and unknown keys are rejected by the view rather than - dropped, so a client typo is a 400 instead of a silent no-op. + Unknown keys are rejected rather than dropped, so a client typo is a 400 + instead of a silent no-op. """ - foreman_signed_off = serializers.BooleanField(required=False) - timesheets_collected = serializers.BooleanField(required=False) - materials_checked = serializers.BooleanField(required=False) - customer_called = serializers.BooleanField(required=False) - released = serializers.BooleanField(required=False) + class Meta: + model = Job + fields = Job.COMPLETION_CHECKLIST_FIELDS + extra_kwargs = {field: {"required": False} for field in fields} + + def validate(self, attrs: dict[str, bool]) -> dict[str, bool]: + unknown = sorted(set(self.initial_data) - set(self.fields)) + if unknown: + raise serializers.ValidationError( + f"Unknown checklist item(s): {', '.join(unknown)}." + ) + return attrs class JobFinishResponseSerializer(serializers.Serializer[FinishJobPayload]): diff --git a/apps/job/services/__init__.py b/apps/job/services/__init__.py index 6eb43df58..95517dbb3 100644 --- a/apps/job/services/__init__.py +++ b/apps/job/services/__init__.py @@ -43,6 +43,7 @@ get_job_total_value, get_paid_complete_jobs, recalculate_job_invoicing_state, + update_completion_checklist, ) from .job_summary_pdf_service import JobSummaryPdfService from .kanban_categorization_service import ( @@ -185,5 +186,6 @@ "serialize_validation_report", "sync_job_folder", "to_decimal", + "update_completion_checklist", "wait_until_file_ready", ] diff --git a/apps/job/services/job_service.py b/apps/job/services/job_service.py index 308ddba86..591de0193 100644 --- a/apps/job/services/job_service.py +++ b/apps/job/services/job_service.py @@ -2,12 +2,14 @@ from decimal import Decimal from django.db import transaction -from django.db.models import Sum -from django.db.models.functions import Coalesce from django.utils import timezone -from apps.accounting.enums import InvoiceStatus from apps.accounting.models.invoice import Invoice +from apps.accounting.services.invoice_calculation import ( + INVOICE_VALID_STATUSES, + get_job_invoicing_basis, + get_prior_valid_invoice_total, +) from apps.accounts.models import Staff from apps.job.models import Job from apps.workflow.services.error_persistence import persist_app_error @@ -47,56 +49,36 @@ def archive_complete_jobs(job_ids, staff=None): def get_job_total_value(job: Job) -> Decimal: - """ - Get the total value of a job using the definitive logic: - 1. If invoiced: Use total invoice amount (definitive) - 2. Else if quote job: Use quote revenue - 3. Else (T&M): Use actual revenue - - Args: - job: Job instance + """The total value of a job. - Returns: - Decimal: Total job value + Invoices are definitive once raised; before that the job is worth whatever + its pricing basis says. Both figures come from ``invoice_calculation``, so + this cannot report a value the job could not actually be invoiced for. """ - # Check for invoices first - they override everything - INVOICE_VALID_STATUSES = [ - status - for (status, _) in InvoiceStatus.choices - if status not in ["VOIDED", "DELETED"] - ] - - total_invoiced = Decimal( - Invoice.objects.filter( - job_id=job.id, status__in=INVOICE_VALID_STATUSES - ).aggregate(total=Coalesce(Sum("total_excl_tax"), Decimal("0")))["total"] - ) - + total_invoiced = get_prior_valid_invoice_total(job) if total_invoiced > 0: return total_invoiced - # No invoices - check pricing methodology - if job.pricing_methodology == "fixed_price": - quote = job.get_latest("quote") - if quote and quote.summary: - return Decimal(str(quote.summary.get("rev", 0))) - return Decimal("0.00") - else: - # T&M job - use actual - actual = job.get_latest("actual") - if actual and actual.summary: - return Decimal(str(actual.summary.get("rev", 0))) - return Decimal("0.00") + return get_job_invoicing_basis(job).target_total + + +def update_completion_checklist( + job: Job, updates: dict[str, bool], staff: Staff +) -> Job: + """Tick or untick front-desk checklist items. + + Job.save() turns each changed field into a job-history event through + _FIELD_HANDLERS, so there is no audit code here to keep in step. Validation + of the keys and values belongs to the serializer that accepted them. + """ + for item, value in updates.items(): + setattr(job, item, value) + job.save(staff=staff) + return job def recalculate_job_invoicing_state(job_id: str, staff) -> None: try: - INVOICE_VALID_STATUSES = [ - status - for (status, _) in InvoiceStatus.choices - if status not in ["VOIDED", "DELETED"] - ] - has_invoices = Invoice.objects.filter( job_id=job_id, status__in=INVOICE_VALID_STATUSES ).exists() @@ -111,19 +93,13 @@ def recalculate_job_invoicing_state(job_id: str, staff) -> None: job = Job.objects.select_related("latest_actual", "latest_quote").get(pk=job_id) - total_invoiced = Decimal( - Invoice.objects.filter( - job_id=job_id, status__in=INVOICE_VALID_STATUSES - ).aggregate(total=Coalesce(Sum("total_excl_tax"), Decimal("0")))["total"] + # Compared against the same value the job would be invoiced for, so a + # capped T&M job cannot read "fully invoiced" at one figure while the + # invoice path uses another. + job.fully_invoiced = ( + get_prior_valid_invoice_total(job) + >= get_job_invoicing_basis(job).target_total ) - - # Fixed-price jobs compare against quote; T&M against actuals - if job.pricing_methodology == "fixed_price" and job.latest_quote: - target_amount = Decimal(str(job.latest_quote.total_revenue)) - else: - target_amount = Decimal(str(job.latest_actual.total_revenue)) - - job.fully_invoiced = total_invoiced >= target_amount job.save(staff=staff, update_fields=["fully_invoiced", "updated_at"]) except Job.DoesNotExist: logger.error("Provided job id doesn't exist") diff --git a/apps/job/tests/test_completion_checklist.py b/apps/job/tests/test_completion_checklist.py index adf4f2966..e60c47065 100644 --- a/apps/job/tests/test_completion_checklist.py +++ b/apps/job/tests/test_completion_checklist.py @@ -6,6 +6,8 @@ not gate. """ +import uuid +from datetime import date from decimal import Decimal from django.urls import reverse @@ -16,7 +18,7 @@ from apps.accounts.models import Staff from apps.company.models import Company from apps.job.models import Job, JobEvent -from apps.job.views.job_rest_views import CHECKLIST_FIELDS +from apps.job.models.costing import CostLine from apps.testing import BaseAPITestCase CHECKLIST_EVENT = "completion_checklist_updated" @@ -55,17 +57,31 @@ def test_a_new_job_has_nothing_ticked(self) -> None: response = self.client.get(self.url) self.assertEqual(response.status_code, 200) - for field in CHECKLIST_FIELDS: + for field in Job.COMPLETION_CHECKLIST_FIELDS: self.assertFalse(response.data["checklist"][field], msg=field) def test_every_item_is_exposed(self) -> None: """The API shape and the field tuple must not drift apart.""" response = self.client.get(self.url) - self.assertEqual(set(response.data["checklist"].keys()), set(CHECKLIST_FIELDS)) + self.assertEqual( + set(response.data["checklist"].keys()), set(Job.COMPLETION_CHECKLIST_FIELDS) + ) # --- Updating --- + def test_a_missing_job_is_not_found(self) -> None: + """A bad job id is a 404, not the 500 the old handler produced.""" + missing = reverse("jobs:job_finish_rest", args=[uuid.uuid4()]) + + self.assertEqual(self.client.get(missing).status_code, 404) + self.assertEqual( + self.client.patch( + missing, data={"released": True}, format="json" + ).status_code, + 404, + ) + def test_ticking_one_item_leaves_the_others_alone(self) -> None: response = self._patch({"materials_checked": True}) @@ -75,7 +91,7 @@ def test_ticking_one_item_leaves_the_others_alone(self) -> None: self.assertFalse(response.data["checklist"]["released"]) def test_every_item_can_be_ticked(self) -> None: - for field in CHECKLIST_FIELDS: + for field in Job.COMPLETION_CHECKLIST_FIELDS: with self.subTest(field=field): response = self._patch({field: True}) self.assertEqual(response.status_code, 200) @@ -93,8 +109,8 @@ def test_unknown_item_is_rejected(self) -> None: self.assertEqual(response.status_code, 400) - def test_non_boolean_value_is_rejected(self) -> None: - response = self._patch({"materials_checked": "yes"}) + def test_a_value_that_is_not_a_boolean_is_rejected(self) -> None: + response = self._patch({"materials_checked": "maybe"}) self.assertEqual(response.status_code, 400) @@ -141,7 +157,7 @@ def test_reticking_the_same_value_adds_no_event(self) -> None: def test_ticking_everything_does_not_change_job_status(self) -> None: original_status = self.job.status - for field in CHECKLIST_FIELDS: + for field in Job.COMPLETION_CHECKLIST_FIELDS: self._patch({field: True}) self.job.refresh_from_db() @@ -170,10 +186,6 @@ def test_ticks_do_not_change_the_invoice_amount(self) -> None: self.assertEqual(before, after) def _add_actual_revenue(self, revenue: Decimal) -> None: - from datetime import date - - from apps.job.models.costing import CostLine - CostLine.objects.create( cost_set=self.job.latest_actual, kind="adjust", diff --git a/apps/job/tests/test_mcp_tool_integration.py b/apps/job/tests/test_mcp_tool_integration.py index 7f5b61845..cfd958cbc 100644 --- a/apps/job/tests/test_mcp_tool_integration.py +++ b/apps/job/tests/test_mcp_tool_integration.py @@ -4,7 +4,6 @@ Tests cover: - QuotingTool functionality - SupplierProductQueryTool functionality -- Tool parameter validation - Error handling in tool execution """ @@ -114,10 +113,6 @@ def setUp(self) -> None: self.tool = QuotingTool() - def test_tool_initialization(self) -> None: - """Test tool initializes correctly""" - self.assertIsInstance(self.tool, QuotingTool) - def test_search_products_basic(self) -> None: """Test basic product search functionality""" result = self.tool.search_products(query="steel") @@ -277,19 +272,6 @@ def setUp(self) -> None: self.tool = SupplierProductQueryTool() - def test_tool_initialization(self) -> None: - """Test tool initializes correctly""" - self.assertIsInstance(self.tool, SupplierProductQueryTool) - - def test_model_attribute(self) -> None: - """Test that model is set to SupplierProduct""" - self.assertEqual(self.tool.model, SupplierProduct) - - def test_exclude_fields(self) -> None: - """Test that supplier and price_list are excluded""" - self.assertIn("supplier", self.tool.exclude_fields) - self.assertIn("price_list", self.tool.exclude_fields) - def test_get_queryset(self) -> None: """Test that get_queryset returns products with related data""" queryset = self.tool.get_queryset() @@ -324,14 +306,6 @@ def setUp(self) -> None: staff=self.test_staff, ) - def test_tool_parameter_validation(self) -> None: - """Test tool parameter validation""" - tool = QuotingTool() - - # Test missing required parameters - with self.assertRaises(TypeError): - tool.search_products() # Missing query parameter - def test_tool_response_is_string(self) -> None: """Test that tools return string responses""" tool = QuotingTool() diff --git a/apps/job/views/job_rest_views.py b/apps/job/views/job_rest_views.py index a399ce623..bc96dbb28 100644 --- a/apps/job/views/job_rest_views.py +++ b/apps/job/views/job_rest_views.py @@ -26,9 +26,9 @@ from rest_framework.response import Response from rest_framework.views import APIView -from apps.accounting.services.finish_job_summary import ( - build_finish_job_summary, - get_job_for_finish_summary, +from apps.accounting.services.finish_job_summary import build_finish_job_summary +from apps.accounting.services.invoice_calculation import ( + get_job_for_invoice_calculation, ) from apps.accounts.models import Staff from apps.job.etag import generate_job_etag @@ -65,6 +65,7 @@ DeltaValidationError, JobRestService, ) +from apps.job.services.job_service import update_completion_checklist from apps.workflow.etag import if_none_match_satisfied from apps.workflow.exceptions import PreconditionFailedError from apps.workflow.models import CompanyDefaults @@ -871,8 +872,6 @@ def get(self, request, job_id): resp = self._set_etag(resp, current_etag) return resp - except Job.DoesNotExist as exc: - raise ValueError(f"Job with id {job_id} not found") from exc except Exception as e: return self.handle_service_error(e) @@ -913,8 +912,6 @@ def get(self, request, job_id): resp = Response(serializer.data, status=status.HTTP_200_OK) return self._set_etag(resp, current_etag) - except Job.DoesNotExist as exc: - raise ValueError(f"Job with id {job_id} not found") from exc except Exception as e: return self.handle_service_error(e) @@ -954,8 +951,6 @@ def get(self, request, job_id): resp = Response(quote, status=status.HTTP_200_OK) return self._set_etag(resp, current_etag) - except Job.DoesNotExist as exc: - raise ValueError(f"Job with id {job_id} not found") from exc except Exception as e: return self.handle_service_error(e) @@ -1080,23 +1075,10 @@ def calculate_profit_margin(cost_set): resp = Response(serializer.data, status=status.HTTP_200_OK) return self._set_etag(resp, current_etag) - except Job.DoesNotExist as exc: - raise ValueError(f"Job with id {job_id} not found") from exc except Exception as e: return self.handle_service_error(e) -# The front-desk checklist items, as Job field names. The update endpoint derives -# its accepted keys from this, so adding an item here is the only change needed. -CHECKLIST_FIELDS = ( - "foreman_signed_off", - "timesheets_collected", - "materials_checked", - "customer_called", - "released", -) - - def _finish_job_payload(job: Job) -> FinishJobPayload: return { "summary": build_finish_job_summary(job), @@ -1104,32 +1086,6 @@ def _finish_job_payload(job: Job) -> FinishJobPayload: } -def _apply_checklist_update(job: Job, updates: dict[str, bool], staff: Staff) -> None: - """Tick or untick checklist items, rejecting anything that is not one. - - Job.save() turns each changed field into a job-history event through - _FIELD_HANDLERS, so there is no audit code here to keep in step. - """ - unknown = sorted(set(updates) - set(CHECKLIST_FIELDS)) - if unknown: - raise ValueError( - f"Unknown checklist item(s): {', '.join(unknown)}. " - f"Valid items: {', '.join(CHECKLIST_FIELDS)}." - ) - - non_boolean = sorted( - key for key, value in updates.items() if not isinstance(value, bool) - ) - if non_boolean: - raise ValueError( - f"Checklist item(s) must be true or false: {', '.join(non_boolean)}." - ) - - for key, value in updates.items(): - setattr(job, key, value) - job.save(staff=staff) - - @method_decorator(csrf_exempt, name="dispatch") class JobFinishRestView(BaseJobRestView): """Finish Job workspace: the authoritative customer balance and checklist. @@ -1155,13 +1111,10 @@ class JobFinishRestView(BaseJobRestView): ) def get(self, request: Request, job_id: UUID) -> Response: try: - job = get_job_for_finish_summary(job_id) + job = get_job_for_invoice_calculation(job_id) serializer = JobFinishResponseSerializer(_finish_job_payload(job)) return Response(serializer.data, status=status.HTTP_200_OK) - except Job.DoesNotExist as exc: - persist_app_error(exc, job_id=job_id) - raise ValueError(f"Job with id {job_id} not found") from exc except Exception as e: return self.handle_service_error(e) @@ -1179,23 +1132,23 @@ def get(self, request: Request, job_id: UUID) -> Response: ) def patch(self, request: Request, job_id: UUID) -> Response: try: - # A checklist item records who confirmed it, so the acting staff - # member must be a real one. IsOfficeStaff already guarantees this; - # the guard makes the attribution contract explicit. + # A tick records who made it, so narrow the authenticated user to a + # real Staff rather than casting (ADR 0028). staff = request.user if not isinstance(staff, Staff): raise ValueError( "Checklist updates require an authenticated staff member." ) - job = get_job_for_finish_summary(job_id) - _apply_checklist_update(job, self.parse_json_body(request), staff) + updates = JobCompletionChecklistUpdateSerializer(data=request.data) + updates.is_valid(raise_exception=True) + + job = update_completion_checklist( + get_job_for_invoice_calculation(job_id), updates.validated_data, staff + ) serializer = JobFinishResponseSerializer(_finish_job_payload(job)) return Response(serializer.data, status=status.HTTP_200_OK) - except Job.DoesNotExist as exc: - persist_app_error(exc, job_id=job_id) - raise ValueError(f"Job with id {job_id} not found") from exc except Exception as e: return self.handle_service_error(e) @@ -1263,8 +1216,6 @@ def get(self, request, job_id): serializer = JobEventsResponseSerializer({"events": events}) return Response(serializer.data, status=status.HTTP_200_OK) - except Job.DoesNotExist as exc: - raise ValueError(f"Job with id {job_id} not found") from exc except Exception as e: return self.handle_service_error(e) @@ -1504,11 +1455,8 @@ def get(self, request, job_id): """ try: # Conditional GET using ETag based on Job.updated_at - try: - job = Job.objects.only("id", "updated_at").get(id=job_id) - current_etag = self._gen_job_etag(job) - except Job.DoesNotExist as exc: - raise ValueError(f"Job with id {job_id} not found") from exc + job = Job.objects.only("id", "updated_at").get(id=job_id) + current_etag = self._gen_job_etag(job) if_none_match = self._get_if_none_match(request) if if_none_match and if_none_match_satisfied(if_none_match, current_etag): diff --git a/apps/workflow/tests/test_access_logging_middleware.py b/apps/workflow/tests/test_access_logging_middleware.py index a44959f8f..8cb48177e 100644 --- a/apps/workflow/tests/test_access_logging_middleware.py +++ b/apps/workflow/tests/test_access_logging_middleware.py @@ -29,10 +29,7 @@ def test_access_log_includes_response_status_and_duration() -> None: assert response.status_code == 418 log_info.assert_called_once() - log_format, *log_args = log_info.call_args.args - assert log_format == ( - "%s\tmethod=%s\tstatus=%s\tduration_ms=%.2f\treplay=%s\tuser=%s\tpath=%s" - ) + _, *log_args = log_info.call_args.args assert log_args[1] == "GET" assert log_args[2] == 418 assert log_args[3] == pytest.approx(123.45) diff --git a/apps/workflow/tests/test_backup_scripts.py b/apps/workflow/tests/test_backup_scripts.py index 72f885eaf..d0d31b991 100644 --- a/apps/workflow/tests/test_backup_scripts.py +++ b/apps/workflow/tests/test_backup_scripts.py @@ -16,7 +16,6 @@ REPO_ROOT = Path(__file__).resolve().parents[3] CLEANUP_BACKUPS = REPO_ROOT / "scripts" / "cleanup_backups.py" -BACKUP_INSTANCE_FILES = REPO_ROOT / "scripts" / "backup_instance_files.sh" PULL_PROD_BACKUP = REPO_ROOT / "scripts" / "pull_prod_backup.sh" @@ -241,7 +240,6 @@ def purge_remote_entries( self.assertEqual(events[0][0], "copy") self.assertIn("daily_20260601.sql.gz", events[0][1]) self.assertEqual(events[1], ("purge", ["daily_20260601.sql.gz"])) - self.assertEqual(cleanup.REMOTE_BASE, "gdrive:dw_backups") self.assertFalse((backup_dir / "daily_20260601.sql.gz").exists()) def test_cleanup_copy_failure_prevents_local_retention_delete(self) -> None: @@ -324,22 +322,6 @@ def test_cleanup_prunes_daily_sha_with_expired_dump(self) -> None: self.assertFalse((backup_dir / "daily_20260601.sha").exists()) self.assertTrue((backup_dir / "daily_20260615.sha").exists()) - def test_file_backup_script_is_incremental_and_scoped(self) -> None: - content = BACKUP_INSTANCE_FILES.read_text() - - self.assertIn('backup_dir "phone-recordings"', content) - self.assertIn('backup_dir "session-replays"', content) - self.assertIn('backup_dir "mediafiles"', content) - self.assertNotIn('backup_dir "dropbox"', content) - self.assertNotIn('backup_dir "adhoc"', content) - self.assertNotIn("tar ", content) - self.assertIn("rclone sync", content) - self.assertIn("--backup-dir", content) - self.assertIn('REMOTE_BASE="gdrive:dw_backups/files"', content) - self.assertIn("ARCHIVE_RETENTION_DAYS=30", content) - self.assertIn("rclone purge", content) - self.assertIn("refusing to back up symlinked directory", content) - class BackportCommandErrorPersistenceTests(TestCase): def test_prelogged_scrub_failure_is_not_persisted_again(self) -> None: diff --git a/frontend/schema.yml b/frontend/schema.yml index 5414dd760..ffa6f3414 100644 --- a/frontend/schema.yml +++ b/frontend/schema.yml @@ -13359,9 +13359,6 @@ components: apps.accounting.services.finish_job_summary, and the frontend formats rather than recomputes them (ADR 0020). properties: - basis: - type: string - readOnly: true job_value_excl_gst: type: number format: double @@ -13427,7 +13424,6 @@ components: exclusiveMinimum: true readOnly: true required: - - basis - job_value_excl_gst - outstanding_invoiced_incl_gst - over_invoiced_excl_gst @@ -14350,6 +14346,8 @@ components: released: type: boolean readOnly: true + description: The job has left our possession, by collection, delivery or + on-site install. required: - customer_called - foreman_signed_off @@ -17818,8 +17816,8 @@ components: description: |- Partial update shape: send only the items being changed. - Every item is optional, and unknown keys are rejected by the view rather than - dropped, so a client typo is a 400 instead of a silent no-op. + Unknown keys are rejected rather than dropped, so a client typo is a 400 + instead of a silent no-op. properties: foreman_signed_off: type: boolean @@ -17831,6 +17829,8 @@ components: type: boolean released: type: boolean + description: The job has left our possession, by collection, delivery or + on-site install. PatchedJobDeltaEnvelopeRequest: type: object description: Serializer that validates the delta envelope submitted by the frontend. diff --git a/frontend/src/api/generated/api.ts b/frontend/src/api/generated/api.ts index cc5b15168..21f03300f 100644 --- a/frontend/src/api/generated/api.ts +++ b/frontend/src/api/generated/api.ts @@ -1789,7 +1789,6 @@ const JobFileThumbnailErrorResponse = z.object({ message: z.string(), }) const FinishJobSummary = z.object({ - basis: z.string(), job_value_excl_gst: z.number().gt(-10000000000).lt(10000000000), valid_invoiced_excl_gst: z.number().gt(-10000000000).lt(10000000000), outstanding_invoiced_incl_gst: z.number().gt(-10000000000).lt(10000000000), diff --git a/frontend/src/components/job/JobFinishTab.vue b/frontend/src/components/job/JobFinishTab.vue index 2c56e171f..754d90965 100644 --- a/frontend/src/components/job/JobFinishTab.vue +++ b/frontend/src/components/job/JobFinishTab.vue @@ -1,10 +1,20 @@ diff --git a/frontend/src/components/job/JobViewTabs.vue b/frontend/src/components/job/JobViewTabs.vue index b79ef77f9..8e0daf174 100644 --- a/frontend/src/components/job/JobViewTabs.vue +++ b/frontend/src/components/job/JobViewTabs.vue @@ -75,8 +75,6 @@ :pricing-methodology="pricingMethodologyString" :job-status="jobStatusString" :paid="props.paid" - @invoice-created="$emit('invoice-created')" - @invoice-deleted="$emit('invoice-deleted')" />
@@ -138,8 +136,6 @@ const emit = defineEmits<{ (e: 'open-attachments'): void (e: 'open-pdf'): void (e: 'quote-imported', result: unknown): void - (e: 'invoice-created'): void - (e: 'invoice-deleted'): void (e: 'delete-job'): void (e: 'reload-job'): void (e: 'job-updated', job: unknown): void diff --git a/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts index 2af2d8a05..c572824b0 100644 --- a/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts +++ b/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' -import { mount, flushPromises } from '@vue/test-utils' +import { flushPromises } from '@vue/test-utils' const { finishRetrieveMock, @@ -35,71 +35,27 @@ vi.mock('vue-sonner', () => ({ })) import JobFinishTab from '../JobFinishTab.vue' +import { + checklistState as checklist, + costSummary, + finishSummary as summary, + inModal, + modalText, + mountFinishTab, + resetFinishTab, +} from './finishTabFixtures' /** * The backend owns every figure here. These tests assert the component renders * what the API returned and never recomputes it — the ADR 0020 boundary that * KAN-323 exists to restore. */ -const summary = (overrides: Record = {}) => ({ - basis: 'quote', - job_value_excl_gst: 1000, - valid_invoiced_excl_gst: 400, - outstanding_invoiced_incl_gst: 460, - remaining_to_invoice_excl_gst: 600, - remaining_gst: 90, - remaining_to_invoice_incl_gst: 690, - total_to_pay_incl_gst: 1150, - over_invoiced_excl_gst: 0, - ...overrides, -}) - -const checklist = () => ({ - foreman_signed_off: false, - timesheets_collected: false, - materials_checked: false, - customer_called: false, - released: false, -}) - -const costSummary = () => ({ - estimate: { cost: 500, rev: 800, hours: 10, profitMargin: 60 }, - quote: { cost: 600, rev: 1000, hours: 12, profitMargin: 66 }, - actual: { cost: 550, rev: 900, hours: 11, profitMargin: 63 }, -}) - -// Mounting to document.body is required for the portalled invoice modal, so each -// test must tear its DOM down or the next test finds the previous modal. -let mounted: ReturnType | null = null - -function mountTab(pricingMethodology = 'fixed_price', jobStatus = 'in_progress') { - mounted = mount(JobFinishTab, { - props: { jobId: 'job-1', pricingMethodology, jobStatus }, - attachTo: document.body, - }) - return mounted -} - -function resetDom() { - mounted?.unmount() - mounted = null - document.body.innerHTML = '' -} +const mountTab = (pricingMethodology = 'fixed_price', jobStatus = 'in_progress') => + mountFinishTab(JobFinishTab, pricingMethodology, jobStatus) const text = (wrapper: ReturnType, id: string) => wrapper.find(`[data-automation-id="${id}"]`).text() -// The invoice modal renders through a reka-ui portal, so it lands on document.body -// rather than inside the mounted wrapper. -const inModal = (id: string) => - document.body.querySelector(`[data-automation-id="${id}"]`) - -const modalText = (id: string) => { - const el = inModal(id) - if (!el) throw new Error(`${id} is not in the modal`) - return el.textContent ?? '' -} - async function openInvoiceModal(wrapper: ReturnType) { await wrapper.find('[data-automation-id="JobFinishTab-create-invoice"]').trigger('click') await flushPromises() @@ -113,7 +69,7 @@ describe('JobFinishTab customer balance', () => { costsSummaryRetrieveMock.mockResolvedValue(costSummary()) }) - afterEach(resetDom) + afterEach(resetFinishTab) it('renders the subtotal, GST and Total to pay returned by the API', async () => { const wrapper = mountTab() @@ -173,7 +129,18 @@ describe('JobFinishTab customer balance', () => { expect(wrapper.find('[data-automation-id="JobFinishTab-create-invoice"]').exists()).toBe(false) expect(wrapper.find('[data-automation-id="JobFinishTab-fully-invoiced"]').exists()).toBe(true) - expect(text(wrapper, 'JobFinishTab-nothing-to-pay')).toContain('Nothing left to pay') + }) + + it('shows an error instead of a zero balance when the load fails', async () => { + // Regression: the catch used to clear `loading` while leaving a fabricated + // zero summary on screen, so a failed request read as a settled job. + finishRetrieveMock.mockRejectedValue(new Error('boom')) + const wrapper = mountTab() + await flushPromises() + + expect(wrapper.find('[data-automation-id="JobFinishTab-load-error"]').exists()).toBe(true) + expect(wrapper.find('[data-automation-id="JobFinishTab-total-to-pay"]').exists()).toBe(false) + expect(wrapper.find('[data-automation-id="JobFinishTab-create-invoice"]').exists()).toBe(false) }) it('reports an over-invoiced job instead of a negative balance', async () => { @@ -248,7 +215,7 @@ describe('JobFinishTab invoice modes', () => { costsSummaryRetrieveMock.mockResolvedValue(costSummary()) }) - afterEach(resetDom) + afterEach(resetFinishTab) it('keeps all three fixed-price modes available', async () => { const wrapper = mountTab('fixed_price') diff --git a/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts index 13e2e54dd..c91bb1450 100644 --- a/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts +++ b/frontend/src/components/job/__tests__/JobFinishTab.checklist.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' -import { mount, flushPromises } from '@vue/test-utils' +import { flushPromises } from '@vue/test-utils' const { finishRetrieveMock, @@ -35,45 +35,17 @@ vi.mock('vue-sonner', () => ({ })) import JobFinishTab from '../JobFinishTab.vue' - -const summary = () => ({ - basis: 'quote', - job_value_excl_gst: 1000, - valid_invoiced_excl_gst: 0, - outstanding_invoiced_incl_gst: 0, - remaining_to_invoice_excl_gst: 1000, - remaining_gst: 150, - remaining_to_invoice_incl_gst: 1150, - total_to_pay_incl_gst: 1150, - over_invoiced_excl_gst: 0, -}) - -const checklist = (overrides: Record = {}) => ({ - foreman_signed_off: false, - timesheets_collected: false, - materials_checked: false, - customer_called: false, - released: false, - ...overrides, -}) - -const ITEMS = [ - 'foreman_signed_off', - 'timesheets_collected', - 'materials_checked', - 'customer_called', - 'released', -] - -let mounted: ReturnType | null = null - -function mountTab(pricingMethodology = 'fixed_price') { - mounted = mount(JobFinishTab, { - props: { jobId: 'job-1', pricingMethodology, jobStatus: 'in_progress' }, - attachTo: document.body, - }) - return mounted -} +import { + CHECKLIST_ITEMS as ITEMS, + checklistState as checklist, + costSummary, + finishSummary as summary, + mountFinishTab, + resetFinishTab, +} from './finishTabFixtures' + +const mountTab = (pricingMethodology = 'fixed_price') => + mountFinishTab(JobFinishTab, pricingMethodology) const item = (wrapper: ReturnType, key: string) => wrapper.find(`[data-automation-id="JobFinishTab-checklist-${key}"]`) @@ -83,34 +55,21 @@ describe('JobFinishTab completion checklist', () => { vi.clearAllMocks() finishRetrieveMock.mockResolvedValue({ summary: summary(), checklist: checklist() }) invoicesRetrieveMock.mockResolvedValue({ invoices: [] }) - costsSummaryRetrieveMock.mockResolvedValue({ - estimate: { cost: 500, rev: 800, hours: 10, profitMargin: 60 }, - quote: { cost: 600, rev: 1000, hours: 12, profitMargin: 66 }, - actual: { cost: 550, rev: 900, hours: 11, profitMargin: 63 }, - }) + costsSummaryRetrieveMock.mockResolvedValue(costSummary()) }) - afterEach(() => { - mounted?.unmount() - mounted = null - document.body.innerHTML = '' - }) - - it('asks the same five questions on a quoted job', async () => { - const wrapper = mountTab('fixed_price') - await flushPromises() + afterEach(resetFinishTab) - for (const key of ITEMS) { - expect(item(wrapper, key).exists()).toBe(true) - } - }) + it('asks the same five questions whatever the pricing methodology', async () => { + for (const methodology of ['fixed_price', 'time_materials']) { + const wrapper = mountTab(methodology) + await flushPromises() - it('asks the same five questions on a T&M job', async () => { - const wrapper = mountTab('time_materials') - await flushPromises() + for (const key of ITEMS) { + expect(item(wrapper, key).exists(), `${methodology}/${key}`).toBe(true) + } - for (const key of ITEMS) { - expect(item(wrapper, key).exists()).toBe(true) + resetFinishTab() } }) diff --git a/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts index f7b1982da..fb27400f7 100644 --- a/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts +++ b/frontend/src/components/job/__tests__/JobFinishTab.labourHours.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' -import { mount, flushPromises } from '@vue/test-utils' +import { flushPromises } from '@vue/test-utils' const { finishRetrieveMock, invoicesRetrieveMock, costsSummaryRetrieveMock } = vi.hoisted(() => ({ finishRetrieveMock: vi.fn(), @@ -27,122 +27,80 @@ vi.mock('vue-sonner', () => ({ })) import JobFinishTab from '../JobFinishTab.vue' +import { + checklistState, + costSummary, + finishSummary, + mountFinishTab, + resetFinishTab, +} from './finishTabFixtures' /** - * KAN-222: office staff read labour budget, hours used and hours remaining - * without doing the subtraction, and an overrun shows as a positive number - * rather than a negative remainder. + * KAN-222: office staff read budget, used and remaining without doing the + * subtraction, and an overrun shows as a positive number rather than a negative + * remainder. */ -const summary = () => ({ - basis: 'quote', - job_value_excl_gst: 1000, - valid_invoiced_excl_gst: 0, - outstanding_invoiced_incl_gst: 0, - remaining_to_invoice_excl_gst: 1000, - remaining_gst: 150, - remaining_to_invoice_incl_gst: 1150, - total_to_pay_incl_gst: 1150, - over_invoiced_excl_gst: 0, -}) - -const checklist = () => ({ - foreman_signed_off: false, - timesheets_collected: false, - materials_checked: false, - customer_called: false, - released: false, -}) - -let mounted: ReturnType | null = null - -function mountWithHours( - { - estimateHours, - quoteHours, - actualHours, - }: { estimateHours: number; quoteHours: number; actualHours: number }, +async function mountWithHours( + hours: { estimate: number; quote: number; actual: number }, pricingMethodology = 'fixed_price', ) { - costsSummaryRetrieveMock.mockResolvedValue({ - estimate: { cost: 500, rev: 800, hours: estimateHours, profitMargin: 60 }, - quote: quoteHours > 0 ? { cost: 600, rev: 1000, hours: quoteHours, profitMargin: 66 } : null, - actual: { cost: 550, rev: 900, hours: actualHours, profitMargin: 63 }, - }) - mounted = mount(JobFinishTab, { - props: { jobId: 'job-1', pricingMethodology, jobStatus: 'in_progress' }, - attachTo: document.body, - }) - return mounted + costsSummaryRetrieveMock.mockResolvedValue(costSummary(hours)) + const wrapper = mountFinishTab(JobFinishTab, pricingMethodology) + await flushPromises() + return wrapper } -const hours = (wrapper: ReturnType, which: string) => +const tile = (wrapper: ReturnType, which: string) => wrapper.find(`[data-automation-id="JobFinishTab-labour-${which}"]`).text() -const remainingLabel = (wrapper: ReturnType) => - wrapper.find('[data-automation-id="JobFinishTab-labour-hours"]').text() - describe('JobFinishTab labour hours', () => { beforeEach(() => { vi.clearAllMocks() - finishRetrieveMock.mockResolvedValue({ summary: summary(), checklist: checklist() }) + finishRetrieveMock.mockResolvedValue({ + summary: finishSummary(), + checklist: checklistState(), + }) invoicesRetrieveMock.mockResolvedValue({ invoices: [] }) }) - afterEach(() => { - mounted?.unmount() - mounted = null - document.body.innerHTML = '' - }) - - it('shows budget, used and remaining for an under-budget job', async () => { - const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 12, actualHours: 8 }) - await flushPromises() - - expect(hours(wrapper, 'budget')).toBe('12') - expect(hours(wrapper, 'used')).toBe('8') - expect(hours(wrapper, 'remaining')).toBe('4') - expect(remainingLabel(wrapper)).toContain('Hours remaining') + afterEach(resetFinishTab) + + it('reports budget, used and remaining-or-overrun', async () => { + const cases = [ + { label: 'under budget', actual: 8, remaining: '4', heading: 'Hours remaining' }, + { label: 'exactly on budget', actual: 12, remaining: '0', heading: 'Hours remaining' }, + { label: 'over budget', actual: 15, remaining: '3', heading: 'Overrun' }, + ] + + for (const { label, actual, remaining, heading } of cases) { + const wrapper = await mountWithHours({ estimate: 10, quote: 12, actual }) + + expect(tile(wrapper, 'budget'), label).toBe('12') + expect(tile(wrapper, 'used'), label).toBe(String(actual)) + expect(tile(wrapper, 'remaining'), label).toBe(remaining) + expect(tile(wrapper, 'remaining'), label).not.toContain('-') + expect( + wrapper.find('[data-automation-id="JobFinishTab-labour-hours"]').text(), + label, + ).toContain(heading) + + resetFinishTab() + } }) - it('shows zero remaining and no overrun exactly on budget', async () => { - const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 12, actualHours: 12 }) - await flushPromises() + it('budgets from quote hours, falling back to estimate hours', async () => { + const cases = [ + { label: 'fixed price with a quote', quote: 12, methodology: 'fixed_price', budget: '12' }, + { label: 'fixed price, no quote', quote: 0, methodology: 'fixed_price', budget: '10' }, + { label: 'time and materials', quote: 12, methodology: 'time_materials', budget: '10' }, + ] - expect(hours(wrapper, 'remaining')).toBe('0') - expect(remainingLabel(wrapper)).toContain('Hours remaining') - expect(remainingLabel(wrapper)).not.toContain('Overrun') - }) - - it('shows an overrun as a positive number, not a negative remainder', async () => { - const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 12, actualHours: 15 }) - await flushPromises() - - expect(hours(wrapper, 'remaining')).toBe('3') - expect(remainingLabel(wrapper)).toContain('Overrun') - expect(hours(wrapper, 'remaining')).not.toContain('-') - }) - - it('budgets a fixed-price job from its quote hours', async () => { - const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 12, actualHours: 5 }) - await flushPromises() - - expect(hours(wrapper, 'budget')).toBe('12') - }) - - it('budgets a fixed-price job with no quote from its estimate hours', async () => { - const wrapper = mountWithHours({ estimateHours: 10, quoteHours: 0, actualHours: 5 }) - await flushPromises() - - expect(hours(wrapper, 'budget')).toBe('10') - }) + for (const { label, quote, methodology, budget } of cases) { + const wrapper = await mountWithHours({ estimate: 10, quote, actual: 5 }, methodology) - it('budgets a T&M job from its estimate hours', async () => { - const wrapper = mountWithHours( - { estimateHours: 10, quoteHours: 12, actualHours: 5 }, - 'time_materials', - ) - await flushPromises() + expect(tile(wrapper, 'budget'), label).toBe(budget) - expect(hours(wrapper, 'budget')).toBe('10') + resetFinishTab() + } }) }) diff --git a/frontend/src/components/job/__tests__/finishTabFixtures.ts b/frontend/src/components/job/__tests__/finishTabFixtures.ts new file mode 100644 index 000000000..84d0588d2 --- /dev/null +++ b/frontend/src/components/job/__tests__/finishTabFixtures.ts @@ -0,0 +1,89 @@ +import { vi } from 'vitest' +import { mount } from '@vue/test-utils' +import type { Component } from 'vue' + +/** Shared fixtures for the JobFinishTab specs, which all mount the same tree. */ + +export const finishSummary = (overrides: Record = {}) => ({ + job_value_excl_gst: 1000, + valid_invoiced_excl_gst: 400, + outstanding_invoiced_incl_gst: 460, + remaining_to_invoice_excl_gst: 600, + remaining_gst: 90, + remaining_to_invoice_incl_gst: 690, + total_to_pay_incl_gst: 1150, + over_invoiced_excl_gst: 0, + ...overrides, +}) + +export const checklistState = (overrides: Record = {}) => ({ + foreman_signed_off: false, + timesheets_collected: false, + materials_checked: false, + customer_called: false, + released: false, + ...overrides, +}) + +export const CHECKLIST_ITEMS = [ + 'foreman_signed_off', + 'timesheets_collected', + 'materials_checked', + 'customer_called', + 'released', +] as const + +export const costSummary = ( + hours: { estimate: number; quote: number; actual: number } = { + estimate: 10, + quote: 12, + actual: 11, + }, +) => ({ + estimate: { cost: 500, rev: 800, hours: hours.estimate, profitMargin: 60 }, + quote: hours.quote > 0 ? { cost: 600, rev: 1000, hours: hours.quote, profitMargin: 66 } : null, + actual: { cost: 550, rev: 900, hours: hours.actual, profitMargin: 63 }, +}) + +let mounted: ReturnType | null = null + +export function mountFinishTab( + component: Component, + pricingMethodology = 'fixed_price', + jobStatus = 'in_progress', +) { + // Mounted to document.body because the invoice modal renders through a + // reka-ui portal; resetFinishTab() must run in afterEach or the next test + // finds the previous modal. + mounted = mount(component, { + props: { jobId: 'job-1', pricingMethodology, jobStatus }, + attachTo: document.body, + }) + return mounted +} + +export function resetFinishTab() { + mounted?.unmount() + mounted = null + document.body.innerHTML = '' +} + +export const inModal = (id: string) => + document.body.querySelector(`[data-automation-id="${id}"]`) + +export const modalText = (id: string) => { + const el = inModal(id) + if (!el) throw new Error(`${id} is not in the modal`) + return el.textContent ?? '' +} + +/** The api-client mock shape every JobFinishTab spec needs. */ +export const finishTabApiMocks = () => ({ + finishRetrieveMock: vi.fn(), + invoicesRetrieveMock: vi.fn(), + costsSummaryRetrieveMock: vi.fn(), + checklistUpdateMock: vi.fn(), + createInvoiceMock: vi.fn(), + deleteInvoiceMock: vi.fn(), + toastErrorMock: vi.fn(), +}) diff --git a/frontend/src/composables/useJobFinancials.ts b/frontend/src/composables/useJobFinancials.ts deleted file mode 100644 index 5e9d22370..000000000 --- a/frontend/src/composables/useJobFinancials.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { ref, type Ref } from 'vue' -import { api } from '../api/client' - -interface JobFinancials { - quoteTotal: number - actualTotal: number - invoiceTotal: number - toBeInvoiced: number -} - -export function useJobFinancials(jobId: Ref) { - const loading = ref(false) - const error = ref(null) - - const fetchJobFinancials = async (pricingMethodology?: string): Promise => { - loading.value = true - error.value = null - - try { - // Fetch both cost summary and invoices in parallel - const [costSummary, invoicesResponse] = await Promise.all([ - api.job_jobs_costs_summary_retrieve({ - params: { job_id: jobId.value }, - }), - api.job_jobs_invoices_retrieve({ - params: { job_id: jobId.value }, - }), - ]) - - // Extract amounts from cost summary - const quoteTotal = Number(costSummary.quote?.rev || 0) - const actualTotal = Number(costSummary.actual?.rev || 0) - - // Calculate invoice total from invoices - const invoices = invoicesResponse.invoices || [] - const invoiceTotal = invoices.reduce( - (sum: number, invoice: { total_excl_tax?: number }) => - sum + Number(invoice.total_excl_tax || 0), - 0, - ) - - // Calculate amount to invoice based on pricing methodology - const amountToInvoice = - pricingMethodology === 'fixed_price' && quoteTotal > 0 ? quoteTotal : actualTotal - - const toBeInvoiced = Math.max(0, amountToInvoice - invoiceTotal) - - return { - quoteTotal, - actualTotal, - invoiceTotal, - toBeInvoiced, - } - } catch (err) { - error.value = 'Failed to fetch job financial data' - console.error('Error fetching job financials:', err) - throw err - } finally { - loading.value = false - } - } - - return { - fetchJobFinancials, - loading: loading as Readonly>, - error: error as Readonly>, - } -} diff --git a/frontend/src/pages/jobs/[id]/(index).vue b/frontend/src/pages/jobs/[id]/(index).vue index 97f0806ab..1969d2690 100644 --- a/frontend/src/pages/jobs/[id]/(index).vue +++ b/frontend/src/pages/jobs/[id]/(index).vue @@ -313,7 +313,6 @@ import { useRoute, useRouter } from 'vue-router' import { useJobsStore } from '@/stores/jobs' import { useJobTabs } from '@/composables/useJobTabs' import { useJobHeaderAutosave } from '@/composables/useJobHeaderAutosave' -import { useJobFinancials } from '@/composables/useJobFinancials' import { useCompanyDefaultsStore } from '@/stores/companyDefaults' import { api } from '@/api/client' import { ArrowLeft, Printer } from 'lucide-vue-next' @@ -450,7 +449,6 @@ const handlePricingMethodologyUpdate = (newMethod: string) => { } // Initialize the job financials composable -const { fetchJobFinancials } = useJobFinancials(jobId) const handleRejectedChange = async () => { if (!jobHeader.value) return @@ -484,14 +482,16 @@ const handleRejectedChange = async () => { } else { // CHECKING - validate no money to be invoiced try { - // Use the composable to fetch financial data - const financials = await fetchJobFinancials(jobHeader.value.pricing_methodology || undefined) + // The server owns this figure; it excludes voided invoices and respects + // the price cap, neither of which the old local calculation did. + const { summary } = await api.job_jobs_finish_retrieve({ + params: { job_id: jobId.value }, + }) - // Check if there's money to be invoiced - if (financials.toBeInvoiced > 0) { + if (summary.remaining_to_invoice_excl_gst > 0) { // Show warning but allow proceeding const confirmed = confirm( - `Warning: Job has ${formatCurrency(financials.toBeInvoiced)} still to be invoiced. Are you sure you want to reject?`, + `Warning: Job has ${formatCurrency(summary.remaining_to_invoice_excl_gst)} still to be invoiced. Are you sure you want to reject?`, ) if (!confirmed) { diff --git a/mypy-baseline.txt b/mypy-baseline.txt index 9d9ff1636..51f22c9f9 100644 --- a/mypy-baseline.txt +++ b/mypy-baseline.txt @@ -819,7 +819,6 @@ apps/job/tests/test_kanban_search.py:0: error: Function is missing a return type apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Invoice" (got "Company | None", expected "Company | Combinable") [misc] apps/job/tests/test_kanban_search.py:0: error: Incompatible type for "company" of "Quote" (got "Company | None", expected "Company | Combinable") [misc] apps/job/tests/test_mcp_tool_integration.py:0: error: Call to untyped function "get_queryset" in typed context [no-untyped-call] -apps/job/tests/test_mcp_tool_integration.py:0: error: Missing positional argument "query" in call to "search_products" of "QuotingTool" [call-arg] apps/job/tests/test_modern_timesheet_views.py:0: error: Item "None" of "XeroPayItem | None" has no attribute "name" [union-attr] apps/job/tests/test_pdf_goldens.py:0: error: Function is missing a return type annotation [no-untyped-def] apps/job/tests/test_quote_modes.py:0: error: Call to untyped function "QuoteModeController" in typed context [no-untyped-call] From 9992798c0258db846a5b20c2cca522710349dcf0 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Sat, 1 Aug 2026 19:32:51 +1200 Subject: [PATCH 38/39] fix: authenticate checklist tests the way the API is actually authenticated The completion-checklist tests used force_login, which only ever worked by accident: JWTAuthentication is the sole authenticator, and it short-circuits to None when ENABLE_JWT_AUTH is off, so the session force_login creates is never consulted. Locally .env turns JWT auth on and the authenticator's middleware fallback honours the session; CI copies .env.precommit, which turns it off, so every request 401'd. force_authenticate replaces the authenticator list outright and is what the rest of the suite uses. Also from review: - Scope the checklist save to the ticked fields. A bare Job.save() rewrites every column held on the instance, so a concurrent write to fully_invoiced or status was reverted to whatever this request read first. - Hold gst_rate to a fraction. The field was unbounded, and the API advertised -10 < rate < 10; a CHECK constraint carries it because the admin, management commands and the Xero sync all bypass serializer validation. - Report a failed balance reload after invoicing instead of leaving the pre-invoice figure on screen looking current. - Drop the casts around invoice creation. The mode arguments were typed str and only fit XeroInvoiceCreateRequest because a cast hid it, and the error payload was typed with a property the code below it did not read. - Give the invoice list stable automation ids so its tests stop selecting by CSS class and list position. --- apps/job/services/job_service.py | 5 ++- apps/job/tests/test_completion_checklist.py | 2 +- .../0020_company_defaults_gst_rate_bounds.py | 38 +++++++++++++++++++ apps/workflow/models/company_defaults.py | 12 ++++++ .../tests/test_company_defaults_api.py | 24 +++++++++++- frontend/schema.yml | 18 +++------ frontend/src/api/generated/api.ts | 6 +-- frontend/src/components/job/JobFinishTab.vue | 15 +++++++- .../src/components/job/JobInvoiceCard.vue | 36 +++++++++++------- .../__tests__/JobFinishTab.balance.test.ts | 6 +-- .../job/__tests__/finishTabFixtures.ts | 18 +++++++-- frontend/tests/job/job-xero-invoice.spec.ts | 2 +- 12 files changed, 139 insertions(+), 43 deletions(-) create mode 100644 apps/workflow/migrations/0020_company_defaults_gst_rate_bounds.py diff --git a/apps/job/services/job_service.py b/apps/job/services/job_service.py index 591de0193..f472cbe5a 100644 --- a/apps/job/services/job_service.py +++ b/apps/job/services/job_service.py @@ -73,7 +73,10 @@ def update_completion_checklist( """ for item, value in updates.items(): setattr(job, item, value) - job.save(staff=staff) + # Scoped to the ticked items so a concurrent write to an unrelated field — + # fully_invoiced, status, costing — is not overwritten with the value this + # request read before the user touched the checkbox. + job.save(staff=staff, update_fields=list(updates.keys())) return job diff --git a/apps/job/tests/test_completion_checklist.py b/apps/job/tests/test_completion_checklist.py index e60c47065..b13240e7d 100644 --- a/apps/job/tests/test_completion_checklist.py +++ b/apps/job/tests/test_completion_checklist.py @@ -46,7 +46,7 @@ def setUp(self) -> None: last_name="Person", is_office_staff=True, ) - self.client.force_login(self.office_staff) + self.client.force_authenticate(user=self.office_staff) def _patch(self, payload: dict[str, object]) -> Response: return self.client.patch(self.url, data=payload, format="json") diff --git a/apps/workflow/migrations/0020_company_defaults_gst_rate_bounds.py b/apps/workflow/migrations/0020_company_defaults_gst_rate_bounds.py new file mode 100644 index 000000000..42447e083 --- /dev/null +++ b/apps/workflow/migrations/0020_company_defaults_gst_rate_bounds.py @@ -0,0 +1,38 @@ +# Generated by Django 6.0.7 on 2026-08-01 07:24 + +from decimal import Decimal + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("company", "0012_text_unset_constraints"), + ("workflow", "0019_company_defaults_gst_rate"), + ] + + operations = [ + migrations.AlterField( + model_name="companydefaults", + name="gst_rate", + field=models.DecimalField( + decimal_places=4, + default=Decimal("0.1500"), + help_text="Sales tax rate applied to amounts DocketWorks quotes before Xero has issued an invoice, as a fraction (0.1500 = 15% NZ GST). Xero remains authoritative for tax on invoices that exist.", + max_digits=5, + validators=[ + django.core.validators.MinValueValidator(Decimal("0")), + django.core.validators.MaxValueValidator(Decimal("0.9999")), + ], + ), + ), + migrations.AddConstraint( + model_name="companydefaults", + constraint=models.CheckConstraint( + condition=models.Q(("gst_rate__gte", 0), ("gst_rate__lt", 1)), + name="companydefaults_gst_rate_is_a_fraction", + ), + ), + ] diff --git a/apps/workflow/models/company_defaults.py b/apps/workflow/models/company_defaults.py index b2fcb10a8..9dfbc9ed0 100644 --- a/apps/workflow/models/company_defaults.py +++ b/apps/workflow/models/company_defaults.py @@ -1,6 +1,7 @@ from collections.abc import Iterable from decimal import Decimal +from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.db.models.base import ModelBase from solo.models import SingletonModel @@ -24,6 +25,10 @@ class CompanyDefaults(SingletonModel): max_digits=5, decimal_places=4, default=Decimal("0.1500"), + validators=[ + MinValueValidator(Decimal("0")), + MaxValueValidator(Decimal("0.9999")), + ], help_text=( "Sales tax rate applied to amounts DocketWorks quotes before Xero has " "issued an invoice, as a fraction (0.1500 = 15% NZ GST). Xero remains " @@ -368,6 +373,13 @@ class Meta: condition=models.Q(id=1), name="companydefaults_singleton", ), + # The validators above only fire through a serializer; the admin, + # management commands and the Xero sync all write straight to the + # model, so the rate is held to a fraction at the database. + models.CheckConstraint( + condition=models.Q(gst_rate__gte=0) & models.Q(gst_rate__lt=1), + name="companydefaults_gst_rate_is_a_fraction", + ), ] @classmethod diff --git a/apps/workflow/tests/test_company_defaults_api.py b/apps/workflow/tests/test_company_defaults_api.py index 75cc22506..2dbb02374 100644 --- a/apps/workflow/tests/test_company_defaults_api.py +++ b/apps/workflow/tests/test_company_defaults_api.py @@ -1,6 +1,7 @@ import uuid +from decimal import Decimal -from django.db import connection +from django.db import IntegrityError, connection, transaction from django.test.utils import CaptureQueriesContext from rest_framework import status from rest_framework.test import APIClient @@ -167,3 +168,24 @@ def test_patch_rejects_xero_quote_terms_over_4000_characters(self) -> None: payload["xero_quote_terms"], ["Ensure this field has no more than 4000 characters."], ) + + def test_patch_rejects_a_gst_rate_outside_a_fraction(self) -> None: + """The rate is a fraction: 0.15 means 15%, so 15 would tax 1500%.""" + for rate in (Decimal("-0.1500"), Decimal("15")): + with self.subTest(rate=rate): + response = self.client.patch( + "/api/company-defaults/", {"gst_rate": rate}, format="json" + ) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn("gst_rate", response.json()) + + def test_a_gst_rate_outside_a_fraction_cannot_reach_the_database(self) -> None: + """The admin, commands and Xero sync all bypass the serializer.""" + defaults = CompanyDefaults.get_solo() + + for rate in (Decimal("-0.1500"), Decimal("1.0000")): + with self.subTest(rate=rate): + defaults.gst_rate = rate + with self.assertRaises(IntegrityError), transaction.atomic(): + defaults.save() diff --git a/frontend/schema.yml b/frontend/schema.yml index ffa6f3414..93bfbbd02 100644 --- a/frontend/schema.yml +++ b/frontend/schema.yml @@ -10867,10 +10867,8 @@ components: gst_rate: type: number format: double - maximum: 10 - minimum: -10 - exclusiveMaximum: true - exclusiveMinimum: true + maximum: 0.9999 + minimum: 0 description: Sales tax rate applied to amounts DocketWorks quotes before Xero has issued an invoice, as a fraction (0.1500 = 15% NZ GST). Xero remains authoritative for tax on invoices that exist. @@ -11265,10 +11263,8 @@ components: gst_rate: type: number format: double - maximum: 10 - minimum: -10 - exclusiveMaximum: true - exclusiveMinimum: true + maximum: 0.9999 + minimum: 0 description: Sales tax rate applied to amounts DocketWorks quotes before Xero has issued an invoice, as a fraction (0.1500 = 15% NZ GST). Xero remains authoritative for tax on invoices that exist. @@ -17319,10 +17315,8 @@ components: gst_rate: type: number format: double - maximum: 10 - minimum: -10 - exclusiveMaximum: true - exclusiveMinimum: true + maximum: 0.9999 + minimum: 0 description: Sales tax rate applied to amounts DocketWorks quotes before Xero has issued an invoice, as a fraction (0.1500 = 15% NZ GST). Xero remains authoritative for tax on invoices that exist. diff --git a/frontend/src/api/generated/api.ts b/frontend/src/api/generated/api.ts index 21f03300f..c2274ada9 100644 --- a/frontend/src/api/generated/api.ts +++ b/frontend/src/api/generated/api.ts @@ -896,7 +896,7 @@ const CompanyDefaults = z.object({ company_acronym: z.string().max(10).nullish(), time_markup: z.number().gt(-1000).lt(1000).optional(), materials_markup: z.number().gt(-1000).lt(1000).optional(), - gst_rate: z.number().gt(-10).lt(10).optional(), + gst_rate: z.number().gte(0).lte(0.9999).optional(), wage_rate: z.number().gt(-10000).lt(10000).optional(), annual_leave_loading: z.number().gt(-1000).lt(1000).optional(), workshop_efficiency_factor: z.number().gt(-10).lt(10).optional(), @@ -963,7 +963,7 @@ const CompanyDefaultsRequest = z.object({ company_acronym: z.string().min(1).max(10).nullish(), time_markup: z.number().gt(-1000).lt(1000).optional(), materials_markup: z.number().gt(-1000).lt(1000).optional(), - gst_rate: z.number().gt(-10).lt(10).optional(), + gst_rate: z.number().gte(0).lte(0.9999).optional(), wage_rate: z.number().gt(-10000).lt(10000).optional(), annual_leave_loading: z.number().gt(-1000).lt(1000).optional(), workshop_efficiency_factor: z.number().gt(-10).lt(10).optional(), @@ -1029,7 +1029,7 @@ const PatchedCompanyDefaultsRequest = z company_acronym: z.string().min(1).max(10).nullable(), time_markup: z.number().gt(-1000).lt(1000), materials_markup: z.number().gt(-1000).lt(1000), - gst_rate: z.number().gt(-10).lt(10), + gst_rate: z.number().gte(0).lte(0.9999), wage_rate: z.number().gt(-10000).lt(10000), annual_leave_loading: z.number().gt(-1000).lt(1000), workshop_efficiency_factor: z.number().gt(-10).lt(10), diff --git a/frontend/src/components/job/JobFinishTab.vue b/frontend/src/components/job/JobFinishTab.vue index 754d90965..6dcd10913 100644 --- a/frontend/src/components/job/JobFinishTab.vue +++ b/frontend/src/components/job/JobFinishTab.vue @@ -109,7 +109,7 @@ :remaining-to-invoice="summary.remaining_to_invoice_excl_gst" :job-status="props.jobStatus" :paid="props.paid" - @invoices-changed="loadFinishSummary" + @invoices-changed="reloadFinishSummary" />
@@ -438,6 +438,19 @@ async function loadAll() { onMounted(loadAll) +// Invoicing changed the balance, so a failed reload must say so rather than +// leave the pre-invoice figure on screen looking current. +async function reloadFinishSummary() { + try { + await loadFinishSummary() + } catch (error) { + log('Failed to reload Finish Job balance: %o', error) + summary.value = null + loadError.value = true + toast.error('Invoice saved, but the balance could not be refreshed. Reload the job.') + } +} + // v-model has already applied the new value optimistically; this persists it and // puts it back if the server refuses, so a tick never survives a failed save. async function onChecklistToggle(key: ChecklistItemKey) { diff --git a/frontend/src/components/job/JobInvoiceCard.vue b/frontend/src/components/job/JobInvoiceCard.vue index 18ee17f14..6aaf258bf 100644 --- a/frontend/src/components/job/JobInvoiceCard.vue +++ b/frontend/src/components/job/JobInvoiceCard.vue @@ -14,7 +14,12 @@ No invoices for this project
-
    +
    • @@ -55,6 +61,7 @@ variant="destructive" size="icon" class="h-7 w-7" + :data-automation-id="`JobInvoiceCard-delete-${invoice.id}`" @click="deleteInvoiceOnXero(invoice.xero_id)" :disabled="!!deletingInvoiceId" > @@ -270,13 +277,14 @@ import { Button } from '../ui/button' import { Card, CardHeader, CardFooter, CardContent, CardDescription, CardTitle } from '../ui/card' import { Input } from '../ui/input' import { Badge } from '../ui/badge' -import type { AxiosError } from 'axios' +import { isAxiosError } from 'axios' import { z } from 'zod' const log = debug('job:invoice') type Invoice = z.infer type XeroInvoiceCreateRequest = z.infer +type XeroInvoiceCreateMode = XeroInvoiceCreateRequest['mode'] // Job statuses that mean the work itself is done. Purely a wording choice — // invoicing stays available at every status. @@ -298,7 +306,7 @@ const deletingInvoiceId = ref(null) const { xeroConnected } = useXeroConnection() const showInvoiceModal = ref(false) -const selectedInvoiceMode = ref(null) +const selectedInvoiceMode = ref(null) const invoicePercentInput = ref('') const invoiceAmountInput = ref('') @@ -352,13 +360,13 @@ function openInvoiceModal() { showInvoiceModal.value = true } -function selectInvoiceMode(mode: string) { +function selectInvoiceMode(mode: XeroInvoiceCreateMode) { selectedInvoiceMode.value = mode invoicePercentInput.value = '' invoiceAmountInput.value = '' } -async function executeCreateInvoice(mode: string) { +async function executeCreateInvoice(mode: XeroInvoiceCreateMode) { if (!props.jobId || isCreatingInvoice.value) return let percent: number | undefined @@ -386,9 +394,11 @@ async function executeCreateInvoice(mode: string) { isCreatingInvoice.value = true try { - const body = { mode } as XeroInvoiceCreateRequest - if (percent !== undefined) body.percent = percent - if (amount !== undefined) body.amount = amount + const body: XeroInvoiceCreateRequest = { + mode, + ...(percent !== undefined && { percent }), + ...(amount !== undefined && { amount }), + } const response = await api.xero_create_invoice_create(body, { params: { job_id: props.jobId }, @@ -406,12 +416,10 @@ async function executeCreateInvoice(mode: string) { } catch (err: unknown) { let msg = 'Unexpected error while trying to create invoice.' log('Error creating invoice: %o', err) - if ((err as AxiosError).isAxiosError) { - const axiosErr = err as AxiosError<{ message: string }> - const errorData = axiosErr.response?.data - if (typeof errorData === 'object' && errorData !== null && 'error' in errorData) { - msg = String((errorData as { error: string }).error) - } + // The payload is typed with the property this code actually reads, so the + // declared shape and the access below cannot drift apart. + if (isAxiosError<{ error?: string }>(err) && err.response?.data?.error) { + msg = err.response.data.error } toast.error(`Failed to create invoice: ${msg}`) } finally { diff --git a/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts b/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts index c572824b0..43ffeea70 100644 --- a/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts +++ b/frontend/src/components/job/__tests__/JobFinishTab.balance.test.ts @@ -195,11 +195,7 @@ describe('JobFinishTab customer balance', () => { const wrapper = mountTab() await flushPromises() - await wrapper - .findAll('button') - .filter((b) => b.classes().join(' ').includes('h-7')) - .at(1)! - .trigger('click') + await wrapper.get('[data-automation-id="JobInvoiceCard-delete-inv-1"]').trigger('click') await flushPromises() expect(deleteInvoiceMock).toHaveBeenCalled() diff --git a/frontend/src/components/job/__tests__/finishTabFixtures.ts b/frontend/src/components/job/__tests__/finishTabFixtures.ts index 84d0588d2..2162fea4c 100644 --- a/frontend/src/components/job/__tests__/finishTabFixtures.ts +++ b/frontend/src/components/job/__tests__/finishTabFixtures.ts @@ -4,7 +4,7 @@ import type { Component } from 'vue' /** Shared fixtures for the JobFinishTab specs, which all mount the same tree. */ -export const finishSummary = (overrides: Record = {}) => ({ +const baseFinishSummary = { job_value_excl_gst: 1000, valid_invoiced_excl_gst: 400, outstanding_invoiced_incl_gst: 460, @@ -13,15 +13,25 @@ export const finishSummary = (overrides: Record = {}) => ({ remaining_to_invoice_incl_gst: 690, total_to_pay_incl_gst: 1150, over_invoiced_excl_gst: 0, - ...overrides, -}) +} -export const checklistState = (overrides: Record = {}) => ({ +const baseChecklistState = { foreman_signed_off: false, timesheets_collected: false, materials_checked: false, customer_called: false, released: false, +} + +// Typed against the base shapes so a typo in an override is a compile error +// rather than a silently ignored key that leaves the default in place. +export const finishSummary = (overrides: Partial = {}) => ({ + ...baseFinishSummary, + ...overrides, +}) + +export const checklistState = (overrides: Partial = {}) => ({ + ...baseChecklistState, ...overrides, }) diff --git a/frontend/tests/job/job-xero-invoice.spec.ts b/frontend/tests/job/job-xero-invoice.spec.ts index 31d2abbde..5cc818a9d 100644 --- a/frontend/tests/job/job-xero-invoice.spec.ts +++ b/frontend/tests/job/job-xero-invoice.spec.ts @@ -29,7 +29,7 @@ test.describe('job xero invoice', () => { await expect(remaining).toBeVisible() await expect(remaining).not.toHaveText(/\$0\.00/) - const invoiceItems = page.locator('ul[role="list"] li') + const invoiceItems = autoId(page, 'JobInvoiceCard-list').locator('li') const initialCount = await invoiceItems.count() const createInvoiceButton = autoId(page, 'JobFinishTab-create-invoice') From 44f305fb39ae771ea10021fb636e5e195e7173a3 Mon Sep 17 00:00:00 2001 From: Corrin Lakeland Date: Sat, 1 Aug 2026 19:42:50 +1200 Subject: [PATCH 39/39] fix: name the icon-only invoice buttons for screen readers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The open and delete buttons on each invoice row carry only an icon, so a screen reader announced them as unlabelled buttons. The label includes the invoice number because these render once per row — five buttons all reading "Delete" would not say which invoice they act on. --- frontend/src/components/job/JobInvoiceCard.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/components/job/JobInvoiceCard.vue b/frontend/src/components/job/JobInvoiceCard.vue index 6aaf258bf..3023d3e08 100644 --- a/frontend/src/components/job/JobInvoiceCard.vue +++ b/frontend/src/components/job/JobInvoiceCard.vue @@ -52,6 +52,7 @@ size="icon" class="h-7 w-7" :data-automation-id="`JobInvoiceCard-open-${invoice.id}`" + :aria-label="`Open invoice ${invoice.number} in Xero`" @click="goToInvoiceOnXero(invoice.online_url)" :disabled="!invoice.online_url" > @@ -62,6 +63,7 @@ size="icon" class="h-7 w-7" :data-automation-id="`JobInvoiceCard-delete-${invoice.id}`" + :aria-label="`Delete invoice ${invoice.number}`" @click="deleteInvoiceOnXero(invoice.xero_id)" :disabled="!!deletingInvoiceId" >