mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-12 19:17:13 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08ea8b90a4 | ||
|
|
12fa696c73 |
No files matched your search
@@ -80,7 +80,7 @@ jobs:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.backend_changed == 'true'
|
||||
name: "Python ${{ matrix.python-version }}"
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
packages: unpaper tesseract-ocr imagemagick ghostscript poppler-utils
|
||||
- name: Configure ImageMagick
|
||||
run: |
|
||||
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-7/policy.xml
|
||||
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
||||
- name: Install Python dependencies
|
||||
env:
|
||||
PYTHON_VERSION: ${{ steps.setup-python.outputs.python-version }}
|
||||
@@ -158,7 +158,7 @@ jobs:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.backend_changed == 'true'
|
||||
name: Check project typing
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
|
||||
@@ -24,10 +24,10 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: ubuntu-26.04
|
||||
- runner: ubuntu-24.04
|
||||
arch: amd64
|
||||
platform: linux/amd64
|
||||
- runner: ubuntu-26.04-arm
|
||||
- runner: ubuntu-24.04-arm
|
||||
arch: arm64
|
||||
platform: linux/arm64
|
||||
runs-on: ${{ matrix.runner }}
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
archive: false
|
||||
merge-and-push:
|
||||
name: Merge and Push Manifest
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build-arch
|
||||
if: needs.build-arch.outputs.should-push == 'true'
|
||||
environment: image-publishing
|
||||
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.docs_changed == 'true'
|
||||
name: Build Documentation
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
||||
- name: Checkout
|
||||
@@ -102,7 +102,7 @@ jobs:
|
||||
name: Deploy Documentation
|
||||
needs: [changes, build]
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.changes.outputs.docs_changed == 'true'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
name: Install Dependencies
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
@@ -104,7 +104,7 @@ jobs:
|
||||
name: Lint
|
||||
needs: [changes, install-dependencies]
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
name: "Unit Tests (${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
||||
needs: [changes, install-dependencies]
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
@@ -188,10 +188,10 @@ jobs:
|
||||
name: E2E Tests
|
||||
needs: [changes, install-dependencies]
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
container: mcr.microsoft.com/playwright:v1.62.1-resolute
|
||||
container: mcr.microsoft.com/playwright:v1.62.1-noble
|
||||
env:
|
||||
PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
@@ -246,7 +246,7 @@ jobs:
|
||||
name: Frontend Build
|
||||
needs: [changes, unit-tests, e2e-tests]
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
|
||||
@@ -14,7 +14,7 @@ permissions: {}
|
||||
jobs:
|
||||
wait-for-docker:
|
||||
name: Wait for Docker Build
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
checks: read
|
||||
statuses: read
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
build-release:
|
||||
name: Build Release
|
||||
needs: wait-for-docker
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
timeout-minutes: 12
|
||||
uses: $/.github/actions/apt-install
|
||||
with:
|
||||
packages: gettext libleptonica6
|
||||
packages: gettext liblept5
|
||||
# ---- Build Documentation ----
|
||||
- name: Build documentation
|
||||
env:
|
||||
@@ -145,7 +145,7 @@ jobs:
|
||||
publish-release:
|
||||
name: Publish Release
|
||||
needs: build-release
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
@@ -197,7 +197,7 @@ jobs:
|
||||
name: Append Changelog
|
||||
needs: publish-release
|
||||
if: needs.publish-release.outputs.prerelease == 'false'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
@@ -15,7 +15,7 @@ permissions:
|
||||
jobs:
|
||||
zizmor:
|
||||
name: Run zizmor
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
uses: zizmorcore/zizmor-action@cc914d7f3750a2d13d75c7f184a1060aa0e9d482 # v0.6.4
|
||||
semgrep:
|
||||
name: Semgrep CE
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
container:
|
||||
image: semgrep/semgrep:1.155.0@sha256:cc869c685dcc0fe497c86258da9f205397d8108e56d21a86082ea4886e52784d
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
cleanup-images:
|
||||
name: Cleanup Image Tags for ${{ matrix.primary-name }}
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
environment: registry-maintenance
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
cleanup-untagged-images:
|
||||
name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }}
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- cleanup-images
|
||||
environment: registry-maintenance
|
||||
|
||||
@@ -21,7 +21,7 @@ on:
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
synchronize-with-crowdin:
|
||||
name: Crowdin Sync
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
environment: translation-sync
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
@@ -7,7 +7,7 @@ jobs:
|
||||
# Note: peakoss/anti-slop does not support the `issues` event yet (all of its
|
||||
# issue inputs are still commented out upstream), so the checks that the PR Bot
|
||||
# workflow gets from the action are implemented manually here.
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
types: [opened]
|
||||
jobs:
|
||||
Anti-slop:
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
ASLOP-PR-VERIFY
|
||||
pr-bot:
|
||||
name: Automated PR Bot
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
# Runs after Anti-slop so the welcome comment can see whether the PR was closed
|
||||
# instead of racing it. Still runs if that job fails, so labeling is not lost.
|
||||
needs: Anti-slop
|
||||
|
||||
@@ -12,7 +12,7 @@ permissions:
|
||||
jobs:
|
||||
pr_opened_or_reopened:
|
||||
name: pr_opened_or_reopened
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
# write permission is required for autolabeler
|
||||
pull-requests: write
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
stale:
|
||||
name: 'Stale'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
lock-threads:
|
||||
name: 'Lock Old Threads'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
close-answered-discussions:
|
||||
name: 'Close Answered Discussions'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
discussions: write
|
||||
steps:
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
close-outdated-discussions:
|
||||
name: 'Close Outdated Discussions'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
discussions: write
|
||||
steps:
|
||||
@@ -211,7 +211,7 @@ jobs:
|
||||
close-unsupported-feature-requests:
|
||||
name: 'Close Unsupported Feature Requests'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
discussions: write
|
||||
steps:
|
||||
|
||||
@@ -8,7 +8,7 @@ env:
|
||||
jobs:
|
||||
generate-translate-strings:
|
||||
name: Generate Translation Strings
|
||||
runs-on: ubuntu-26.04
|
||||
runs-on: ubuntu-latest
|
||||
environment: translation-sync
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
+351
-351
@@ -410,180 +410,179 @@ src/documents/search/_query.py:0: error: Argument 3 to "Term" has incompatible t
|
||||
src/documents/search/_query.py:0: error: Argument 3 to "Term" has incompatible type "**dict[str, int | None]"; expected "bool" [arg-type]
|
||||
src/documents/search/_query.py:0: error: Unexpected keyword argument "children" for "Node" [call-arg]
|
||||
src/documents/search/_schema.py:0: error: Redundant cast to "Path" [redundant-cast]
|
||||
src/documents/search/_schema.py:0: error: Unexpected keyword argument "fast" for "add_json_field" of "SchemaBuilder" [call-arg]
|
||||
src/documents/serialisers.py:0: error: "type[_MT?]" has no attribute "_meta" [attr-defined]
|
||||
src/documents/serialisers.py:0: error: "type[_MT?]" has no attribute "objects" [attr-defined]
|
||||
src/documents/serialisers.py:0: error: "type[_MT?]" has no attribute "objects" [attr-defined]
|
||||
src/documents/serialisers.py:0: error: "type[_MT?]" has no attribute "objects" [attr-defined]
|
||||
src/documents/serialisers.py:0: error: Argument "choices" to "ChoiceField" has incompatible type "type[FieldDataType]"; expected "Sequence[Any]" [arg-type]
|
||||
src/documents/serialisers.py:0: error: Argument "default" to "MultipleChoiceField" has incompatible type "set[DocumentSource]"; expected "set[str | int] | set[str] | set[int] | Callable[[], set[str | int] | set[str] | set[int]] | _Empty | None" [arg-type]
|
||||
src/documents/serialisers.py:0: error: Argument 1 of "get_value" is incompatible with supertype "rest_framework.fields.Field"; supertype defines the argument type as "Mapping[str, Any]" [override]
|
||||
src/documents/serialisers.py:0: error: Argument 1 of "update" is incompatible with supertype "rest_framework.serializers.BaseSerializer"; supertype defines the argument type as "dict[str, Any]" [override]
|
||||
src/documents/serialisers.py:0: error: Argument 1 to "__get__" of "BaseManager" has incompatible type "PrimaryKeyRelatedField[Any]"; expected "Options[Any] | None" [arg-type]
|
||||
src/documents/serialisers.py:0: error: Argument 1 to "get_value_field_name" of "CustomFieldInstance" has incompatible type "str"; expected "FieldDataType" [arg-type]
|
||||
src/documents/serialisers.py:0: error: Argument 1 to "int" has incompatible type "Any | Collection[str]"; expected "str | Buffer | SupportsInt | SupportsIndex" [arg-type]
|
||||
src/documents/serialisers.py:0: error: Argument 1 to "list" has incompatible type "QuerySet[Document, TypedDict({'id': int, 'title': str, 'deleted_at': datetime | None})]"; expected "Iterable[dict[str, Any]]" [arg-type]
|
||||
src/documents/serialisers.py:0: error: Expected iterable as variadic argument [misc]
|
||||
src/documents/serialisers.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "PrimaryKeyRelatedField[Tag]", base class "Field" defined the type as "BaseSerializer[Any]") [assignment]
|
||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "Sequence[str] | tuple[Lower]", variable has type "Sequence[str] | None") [assignment]
|
||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "WorkflowActionWebhookSerializer", variable has type "WorkflowActionEmailSerializer") [assignment]
|
||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "type[Correspondent]", variable has type "type[Tag] | None") [assignment]
|
||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "type[DocumentType]", variable has type "type[Tag] | None") [assignment]
|
||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "type[SearchResultListSerializer]", base class "Meta" defined the type as "type[OwnedObjectListSerializer]") [assignment]
|
||||
src/documents/serialisers.py:0: error: Incompatible types in assignment (expression has type "type[StoragePath]", variable has type "type[Tag] | None") [assignment]
|
||||
src/documents/serialisers.py:0: error: Item "Field[Any, Any, Any, Any]" of "Field[Any, Any, Any, Any] | None" has no attribute "fetch_documents" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "Field[Any, Any, Any, Any]" of "Field[Any, Any, Any, Any] | None" has no attribute "get_shared_object_pks" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "Field[Any, Any, Any, Any]" of "Field[Any, Any, Any, Any] | None" has no attribute "get_shared_object_pks" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "Any | None" has no attribute "pk" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "CustomField | None" has no attribute "name" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "context" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "context" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "context" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "fetch_documents" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "get_shared_object_pks" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "get_shared_object_pks" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Item "list[str]" of "Any | list[str]" has no attribute "values_list" [union-attr]
|
||||
src/documents/serialisers.py:0: error: Missing type arguments for generic type "Field" [type-arg]
|
||||
src/documents/serialisers.py:0: error: Missing type arguments for generic type "Iterable" [type-arg]
|
||||
src/documents/serialisers.py:0: error: Missing type arguments for generic type "dict" [type-arg]
|
||||
src/documents/serialisers.py:0: error: Missing type arguments for generic type "dict" [type-arg]
|
||||
src/documents/serialisers.py:0: error: Missing type arguments for generic type "dict" [type-arg]
|
||||
src/documents/serialisers.py:0: error: Need type annotation for "document" [var-annotated]
|
||||
src/documents/serialisers.py:0: error: Need type annotation for "documents" [var-annotated]
|
||||
src/documents/serialisers.py:0: error: Need type annotation for "permissions_dict" [var-annotated]
|
||||
src/documents/serialisers.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload]
|
||||
src/documents/serialisers.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload]
|
||||
src/documents/serialisers.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload]
|
||||
src/documents/serialisers.py:0: error: Skipping analyzing "auditlog.context": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
||||
src/documents/serialisers.py:0: error: Unsupported target for indexed assignment ("Mapping[str, Any] | Any") [index]
|
||||
src/documents/serialisers.py:0: error: Unsupported target for indexed assignment ("Mapping[str, Any] | Any") [index]
|
||||
src/documents/serialisers.py:0: error: Unsupported target for indexed assignment ("Mapping[str, Any] | Any") [index]
|
||||
src/documents/serialisers.py:0: error: Unsupported target for indexed assignment ("Mapping[str, Any]") [index]
|
||||
src/documents/serialisers.py:0: error: Value of type "Any | None" is not indexable [index]
|
||||
src/documents/serialisers.py:0: error: Value of type "Any | None" is not indexable [index]
|
||||
src/documents/serialisers.py:0: error: Value of type "Match[str] | None" is not indexable [index]
|
||||
src/documents/serialisers/base.py:0: error: "type[_MT?]" has no attribute "_meta" [attr-defined]
|
||||
src/documents/serialisers/base.py:0: error: "type[_MT?]" has no attribute "objects" [attr-defined]
|
||||
src/documents/serialisers/base.py:0: error: "type[_MT?]" has no attribute "objects" [attr-defined]
|
||||
src/documents/serialisers/base.py:0: error: "type[_MT?]" has no attribute "objects" [attr-defined]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/base.py:0: error: Item "Field[Any, Any, Any, Any]" of "Field[Any, Any, Any, Any] | None" has no attribute "get_shared_object_pks" [union-attr]
|
||||
src/documents/serialisers/base.py:0: error: Item "None" of "Any | None" has no attribute "name" [union-attr]
|
||||
src/documents/serialisers/base.py:0: error: Item "None" of "Any | None" has no attribute "pk" [union-attr]
|
||||
src/documents/serialisers/base.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "context" [union-attr]
|
||||
src/documents/serialisers/base.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "get_shared_object_pks" [union-attr]
|
||||
src/documents/serialisers/base.py:0: error: Item "list[str]" of "Any | list[str]" has no attribute "values_list" [union-attr]
|
||||
src/documents/serialisers/base.py:0: error: Missing type arguments for generic type "Iterable" [type-arg]
|
||||
src/documents/serialisers/base.py:0: error: Missing type arguments for generic type "dict" [type-arg]
|
||||
src/documents/serialisers/base.py:0: error: Need type annotation for "permissions_dict" [var-annotated]
|
||||
src/documents/serialisers/base.py:0: error: Unsupported target for indexed assignment ("Mapping[str, Any] | Any") [index]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Incompatible types in assignment (expression has type "type[Correspondent]", variable has type "type[Tag] | None") [assignment]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Incompatible types in assignment (expression has type "type[DocumentType]", variable has type "type[Tag] | None") [assignment]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Incompatible types in assignment (expression has type "type[StoragePath]", variable has type "type[Tag] | None") [assignment]
|
||||
src/documents/serialisers/bulk_edit.py:0: error: Missing type arguments for generic type "dict" [type-arg]
|
||||
src/documents/serialisers/documents.py:0: error: Argument 1 of "update" is incompatible with supertype "rest_framework.serializers.BaseSerializer"; supertype defines the argument type as "dict[str, Any]" [override]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/documents.py:0: error: Incompatible types in assignment (expression has type "type[SearchResultListSerializer]", base class "Meta" defined the type as "type[OwnedObjectListSerializer]") [assignment]
|
||||
src/documents/serialisers/documents.py:0: error: Item "Field[Any, Any, Any, Any]" of "Field[Any, Any, Any, Any] | None" has no attribute "fetch_documents" [union-attr]
|
||||
src/documents/serialisers/documents.py:0: error: Item "Field[Any, Any, Any, Any]" of "Field[Any, Any, Any, Any] | None" has no attribute "get_shared_object_pks" [union-attr]
|
||||
src/documents/serialisers/documents.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "context" [union-attr]
|
||||
src/documents/serialisers/documents.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "context" [union-attr]
|
||||
src/documents/serialisers/documents.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "fetch_documents" [union-attr]
|
||||
src/documents/serialisers/documents.py:0: error: Item "None" of "Field[Any, Any, Any, Any] | None" has no attribute "get_shared_object_pks" [union-attr]
|
||||
src/documents/serialisers/documents.py:0: error: Skipping analyzing "auditlog.context": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
||||
src/documents/serialisers/documents.py:0: error: Unsupported target for indexed assignment ("Mapping[str, Any] | Any") [index]
|
||||
src/documents/serialisers/documents.py:0: error: Unsupported target for indexed assignment ("Mapping[str, Any] | Any") [index]
|
||||
src/documents/serialisers/documents.py:0: error: Value of type "Any | None" is not indexable [index]
|
||||
src/documents/serialisers/metadata.py:0: error: Argument "choices" to "ChoiceField" has incompatible type "type[FieldDataType]"; expected "Sequence[Any]" [arg-type]
|
||||
src/documents/serialisers/metadata.py:0: error: Argument 1 of "get_value" is incompatible with supertype "rest_framework.fields.Field"; supertype defines the argument type as "Mapping[str, Any]" [override]
|
||||
src/documents/serialisers/metadata.py:0: error: Argument 1 to "__get__" of "BaseManager" has incompatible type "PrimaryKeyRelatedField[Any]"; expected "Options[Any] | None" [arg-type]
|
||||
src/documents/serialisers/metadata.py:0: error: Argument 1 to "get_value_field_name" of "CustomFieldInstance" has incompatible type "str"; expected "FieldDataType" [arg-type]
|
||||
src/documents/serialisers/metadata.py:0: error: Expected iterable as variadic argument [misc]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/metadata.py:0: error: Incompatible types in assignment (expression has type "PrimaryKeyRelatedField[Tag]", base class "Field" defined the type as "BaseSerializer[Any]") [assignment]
|
||||
src/documents/serialisers/metadata.py:0: error: Incompatible types in assignment (expression has type "Sequence[str] | tuple[Lower]", variable has type "Sequence[str] | None") [assignment]
|
||||
src/documents/serialisers/metadata.py:0: error: Item "None" of "CustomField | None" has no attribute "name" [union-attr]
|
||||
src/documents/serialisers/metadata.py:0: error: Missing type arguments for generic type "Field" [type-arg]
|
||||
src/documents/serialisers/metadata.py:0: error: Missing type arguments for generic type "dict" [type-arg]
|
||||
src/documents/serialisers/metadata.py:0: error: Need type annotation for "document" [var-annotated]
|
||||
src/documents/serialisers/metadata.py:0: error: Unsupported target for indexed assignment ("Mapping[str, Any]") [index]
|
||||
src/documents/serialisers/metadata.py:0: error: Value of type "Any | None" is not indexable [index]
|
||||
src/documents/serialisers/saved_views.py:0: error: Argument 1 to "int" has incompatible type "Any | Collection[str]"; expected "str | Buffer | SupportsInt | SupportsIndex" [arg-type]
|
||||
src/documents/serialisers/saved_views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/saved_views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/saved_views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/saved_views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/saved_views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/saved_views.py:0: error: Value of type "Match[str] | None" is not indexable [index]
|
||||
src/documents/serialisers/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/sharing.py:0: error: Need type annotation for "documents" [var-annotated]
|
||||
src/documents/serialisers/system.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/system.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/tasks.py:0: error: Argument 1 to "list" has incompatible type "QuerySet[Document, TypedDict({'id': int, 'title': str, 'deleted_at': datetime | None})]"; expected "Iterable[dict[str, Any]]" [arg-type]
|
||||
src/documents/serialisers/tasks.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/tasks.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/tasks.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/tasks.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload]
|
||||
src/documents/serialisers/tasks.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload]
|
||||
src/documents/serialisers/tasks.py:0: error: No overload variant of "get" of "dict" matches argument types "str", "str" [call-overload]
|
||||
src/documents/serialisers/upload.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/upload.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/upload.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/upload.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/upload.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/upload.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/upload.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Argument "default" to "MultipleChoiceField" has incompatible type "set[DocumentSource]"; expected "set[str | int] | set[str] | set[int] | Callable[[], set[str | int] | set[str] | set[int]] | _Empty | None" [arg-type]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/serialisers/workflows.py:0: error: Incompatible types in assignment (expression has type "WorkflowActionWebhookSerializer", variable has type "WorkflowActionEmailSerializer") [assignment]
|
||||
src/documents/signals/handlers.py:0: error: "BaseDatabaseWrapper" has no attribute "close_pool" [attr-defined]
|
||||
src/documents/signals/handlers.py:0: error: "BaseDatabaseWrapper" has no attribute "close_pool" [attr-defined]
|
||||
src/documents/signals/handlers.py:0: error: "Task[[int, int], Any]" has no attribute "delay_on_commit" [attr-defined]
|
||||
@@ -1525,180 +1524,181 @@ src/documents/utils.py:0: error: Incompatible types in assignment (expression ha
|
||||
src/documents/utils.py:0: error: Missing type arguments for generic type "CompletedProcess" [type-arg]
|
||||
src/documents/validators.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/versioning.py:0: error: Missing type arguments for generic type "Prefetch" [type-arg]
|
||||
src/documents/views.py:0: error: "BulkPermissionMixin" has no attribute "filter_queryset" [attr-defined]
|
||||
src/documents/views.py:0: error: "BulkPermissionMixin" has no attribute "get_queryset" [attr-defined]
|
||||
src/documents/views.py:0: error: "BulkPermissionMixin" has no attribute "queryset" [attr-defined]
|
||||
src/documents/views.py:0: error: "BulkPermissionMixin" has no attribute "queryset" [attr-defined]
|
||||
src/documents/views.py:0: error: "Sequence[_SupportsHasPermission]" has no attribute "append" [attr-defined]
|
||||
src/documents/views.py:0: error: "get_serializer_context" undefined in superclass [misc]
|
||||
src/documents/views.py:0: error: "object" has no attribute "apply_async" [attr-defined]
|
||||
src/documents/views.py:0: error: "type[DocumentFilterSet]" has no attribute "declared_filters" [attr-defined]
|
||||
src/documents/views.py:0: error: "type[Model]" has no attribute "objects" [attr-defined]
|
||||
src/documents/views.py:0: error: Argument "filename" to "FileResponse" has incompatible type "str | Any | None"; expected "str" [arg-type]
|
||||
src/documents/views.py:0: error: Argument "path" to "EmailAttachment" has incompatible type "Path | None"; expected "Path" [arg-type]
|
||||
src/documents/views.py:0: error: Argument "user" to "_has_document_permissions" of "DocumentOperationPermissionMixin" has incompatible type "User | AnonymousUser"; expected "User" [arg-type]
|
||||
src/documents/views.py:0: error: Argument "user" to "_has_document_permissions" of "DocumentOperationPermissionMixin" has incompatible type "User | AnonymousUser"; expected "User" [arg-type]
|
||||
src/documents/views.py:0: error: Argument "user" to "_resolve_document_ids" of "DocumentSelectionMixin" has incompatible type "User | AnonymousUser"; expected "User" [arg-type]
|
||||
src/documents/views.py:0: error: Argument "user" to "_resolve_document_ids" of "DocumentSelectionMixin" has incompatible type "User | AnonymousUser"; expected "User" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 1 to "TaskSummarySerializer" has incompatible type "QuerySet[PaperlessTask@AnnotatedWith[TypedDict({'total_count': int, 'pending_count': int, 'success_count': int, 'failure_count': int, 'avg_duration_seconds': Any, 'avg_wait_time_seconds': Any, 'last_run': Any, 'last_success': Any, 'last_failure': Any})], TypedDict({'task_type': str, 'total_count': Any, 'pending_count': Any, 'success_count': Any, 'failure_count': Any, 'avg_duration_seconds': Any, 'avg_wait_time_seconds': Any, 'last_run': Any, 'last_success': Any, 'last_failure': Any})]"; expected "dict[str, Any] | None" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 1 to "int" has incompatible type "Any | Collection[str]"; expected "str | Buffer | SupportsInt | SupportsIndex" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 1 to "int" has incompatible type "Any | Collection[str]"; expected "str | Buffer | SupportsInt | SupportsIndex" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 1 to "paginate_queryset" of "GenericAPIView" has incompatible type "TantivyRelevanceList"; expected "QuerySet[Any, _MT_co] | Sequence[_MT_co]" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 1 to "permitted_document_ids" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 1 to "permitted_object_ids" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 2 to "match_correspondents" has incompatible type "DocumentClassifier | None"; expected "DocumentClassifier" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 2 to "match_document_types" has incompatible type "DocumentClassifier | None"; expected "DocumentClassifier" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 2 to "match_storage_paths" has incompatible type "DocumentClassifier | None"; expected "DocumentClassifier" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 2 to "match_tags" has incompatible type "DocumentClassifier | None"; expected "DocumentClassifier" [arg-type]
|
||||
src/documents/views.py:0: error: Argument 3 to "autocomplete" of "TantivyBackend" has incompatible type "User | AnonymousUser | None"; expected "AbstractUser | None" [arg-type]
|
||||
src/documents/views.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "dict[Any, Any]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "ClassificationSuggestions", variable has type "dict[Any, Any]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Document, Document]", variable has type "list[Any]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "int", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "tuple[type[IsAuthenticated], type[ViewDocumentsPermissions]]", variable has type "tuple[type[IsAuthenticated], type[PaperlessObjectPermissions]]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "type[ArchiveOnlyStrategy]", variable has type "type[OriginalAndArchiveStrategy]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "type[DocumentSerializer]", variable has type "type[TrashSerializer]") [assignment]
|
||||
src/documents/views.py:0: error: Incompatible types in assignment (expression has type "type[OriginalsOnlyStrategy]", variable has type "type[OriginalAndArchiveStrategy]") [assignment]
|
||||
src/documents/views.py:0: error: Item "AnonymousUser" of "User | AnonymousUser" has no attribute "get_full_name" [union-attr]
|
||||
src/documents/views.py:0: error: Item "BasePagination" of "BasePagination | None" has no attribute "get_page_size" [union-attr]
|
||||
src/documents/views.py:0: error: Item "BasePagination" of "BasePagination | None" has no attribute "page_size" [union-attr]
|
||||
src/documents/views.py:0: error: Item "None" of "Any | None" has no attribute "get" [union-attr]
|
||||
src/documents/views.py:0: error: Item "None" of "Any | None" has no attribute "get" [union-attr]
|
||||
src/documents/views.py:0: error: Item "None" of "ApplicationConfiguration | None" has no attribute "app_logo" [union-attr]
|
||||
src/documents/views.py:0: error: Item "None" of "BasePagination | None" has no attribute "get_page_size" [union-attr]
|
||||
src/documents/views.py:0: error: Item "None" of "BasePagination | None" has no attribute "page_size" [union-attr]
|
||||
src/documents/views.py:0: error: Missing positional argument "request" in call to "email_documents" [call-arg]
|
||||
src/documents/views.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg]
|
||||
src/documents/views.py:0: error: Missing type arguments for generic type "list" [type-arg]
|
||||
src/documents/views.py:0: error: Missing type arguments for generic type "list" [type-arg]
|
||||
src/documents/views.py:0: error: Missing type arguments for generic type "list" [type-arg]
|
||||
src/documents/views.py:0: error: Missing type arguments for generic type "list" [type-arg]
|
||||
src/documents/views.py:0: error: Need type annotation for "authentication_classes" (hint: "authentication_classes: list[<type>] = ...") [var-annotated]
|
||||
src/documents/views.py:0: error: Need type annotation for "children_map" (hint: "children_map: dict[<type>, <type>] = ...") [var-annotated]
|
||||
src/documents/views.py:0: error: Need type annotation for "doc" [var-annotated]
|
||||
src/documents/views.py:0: error: Need type annotation for "doc" [var-annotated]
|
||||
src/documents/views.py:0: error: Need type annotation for "docs" (hint: "docs: list[<type>] = ...") [var-annotated]
|
||||
src/documents/views.py:0: error: Need type annotation for "permission_classes" (hint: "permission_classes: list[<type>] = ...") [var-annotated]
|
||||
src/documents/views.py:0: error: Need type annotation for "ui_settings" (hint: "ui_settings: dict[<type>, <type>] = ...") [var-annotated]
|
||||
src/documents/views.py:0: error: No overload variant of "prefetch_related" of "QuerySet" matches argument type "list[object]" [call-overload]
|
||||
src/documents/views.py:0: error: Skipping analyzing "auditlog.models": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
||||
src/documents/views.py:0: error: Skipping analyzing "langdetect": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
||||
src/documents/views.py:0: error: Unsupported operand types for + ("None" and "int") [operator]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[CustomField]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Group]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[User]" is not indexable [index]
|
||||
src/documents/views.py:0: error: Value of type "Iterable[Workflow]" is not indexable [index]
|
||||
src/documents/views/base.py:0: error: "BulkPermissionMixin" has no attribute "filter_queryset" [attr-defined]
|
||||
src/documents/views/base.py:0: error: "BulkPermissionMixin" has no attribute "get_queryset" [attr-defined]
|
||||
src/documents/views/base.py:0: error: "BulkPermissionMixin" has no attribute "queryset" [attr-defined]
|
||||
src/documents/views/base.py:0: error: "BulkPermissionMixin" has no attribute "queryset" [attr-defined]
|
||||
src/documents/views/base.py:0: error: "get_serializer_context" undefined in superclass [misc]
|
||||
src/documents/views/base.py:0: error: "type[Model]" has no attribute "objects" [attr-defined]
|
||||
src/documents/views/base.py:0: error: Argument "user" to "_has_document_permissions" of "DocumentOperationPermissionMixin" has incompatible type "User | AnonymousUser"; expected "User" [arg-type]
|
||||
src/documents/views/base.py:0: error: Argument "user" to "_resolve_document_ids" of "DocumentSelectionMixin" has incompatible type "User | AnonymousUser"; expected "User" [arg-type]
|
||||
src/documents/views/base.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/base.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/base.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/base.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/base.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views/base.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views/base.py:0: error: Missing type arguments for generic type "list" [type-arg]
|
||||
src/documents/views/bulk_edit.py:0: error: Argument "user" to "_has_document_permissions" of "DocumentOperationPermissionMixin" has incompatible type "User | AnonymousUser"; expected "User" [arg-type]
|
||||
src/documents/views/bulk_edit.py:0: error: Argument "user" to "_resolve_document_ids" of "DocumentSelectionMixin" has incompatible type "User | AnonymousUser"; expected "User" [arg-type]
|
||||
src/documents/views/bulk_edit.py:0: error: Argument 1 to "int" has incompatible type "Any | Collection[str]"; expected "str | Buffer | SupportsInt | SupportsIndex" [arg-type]
|
||||
src/documents/views/bulk_edit.py:0: error: Argument 1 to "permitted_object_ids" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/bulk_edit.py:0: error: Incompatible types in assignment (expression has type "type[ArchiveOnlyStrategy]", variable has type "type[OriginalAndArchiveStrategy]") [assignment]
|
||||
src/documents/views/bulk_edit.py:0: error: Incompatible types in assignment (expression has type "type[OriginalsOnlyStrategy]", variable has type "type[OriginalAndArchiveStrategy]") [assignment]
|
||||
src/documents/views/bulk_edit.py:0: error: Skipping analyzing "auditlog.models": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
||||
src/documents/views/chat.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: "type[DocumentFilterSet]" has no attribute "declared_filters" [attr-defined]
|
||||
src/documents/views/documents.py:0: error: Argument "path" to "EmailAttachment" has incompatible type "Path | None"; expected "Path" [arg-type]
|
||||
src/documents/views/documents.py:0: error: Argument 1 to "paginate_queryset" of "GenericAPIView" has incompatible type "TantivyRelevanceList"; expected "QuerySet[Any, _MT_co] | Sequence[_MT_co]" [arg-type]
|
||||
src/documents/views/documents.py:0: error: Argument 2 to "match_correspondents" has incompatible type "DocumentClassifier | None"; expected "DocumentClassifier" [arg-type]
|
||||
src/documents/views/documents.py:0: error: Argument 2 to "match_document_types" has incompatible type "DocumentClassifier | None"; expected "DocumentClassifier" [arg-type]
|
||||
src/documents/views/documents.py:0: error: Argument 2 to "match_storage_paths" has incompatible type "DocumentClassifier | None"; expected "DocumentClassifier" [arg-type]
|
||||
src/documents/views/documents.py:0: error: Argument 2 to "match_tags" has incompatible type "DocumentClassifier | None"; expected "DocumentClassifier" [arg-type]
|
||||
src/documents/views/documents.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
src/documents/views/documents.py:0: error: Incompatible types in assignment (expression has type "ClassificationSuggestions", variable has type "dict[Any, Any]") [assignment]
|
||||
src/documents/views/documents.py:0: error: Item "BasePagination" of "BasePagination | None" has no attribute "get_page_size" [union-attr]
|
||||
src/documents/views/documents.py:0: error: Item "BasePagination" of "BasePagination | None" has no attribute "page_size" [union-attr]
|
||||
src/documents/views/documents.py:0: error: Item "None" of "BasePagination | None" has no attribute "get_page_size" [union-attr]
|
||||
src/documents/views/documents.py:0: error: Item "None" of "BasePagination | None" has no attribute "page_size" [union-attr]
|
||||
src/documents/views/documents.py:0: error: Missing positional argument "request" in call to "email_documents" [call-arg]
|
||||
src/documents/views/documents.py:0: error: Missing type arguments for generic type "list" [type-arg]
|
||||
src/documents/views/documents.py:0: error: Missing type arguments for generic type "list" [type-arg]
|
||||
src/documents/views/documents.py:0: error: Missing type arguments for generic type "list" [type-arg]
|
||||
src/documents/views/documents.py:0: error: Need type annotation for "doc" [var-annotated]
|
||||
src/documents/views/documents.py:0: error: Need type annotation for "doc" [var-annotated]
|
||||
src/documents/views/documents.py:0: error: No overload variant of "prefetch_related" of "QuerySet" matches argument type "list[object]" [call-overload]
|
||||
src/documents/views/documents.py:0: error: Skipping analyzing "auditlog.models": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
||||
src/documents/views/documents.py:0: error: Skipping analyzing "langdetect": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
||||
src/documents/views/documents.py:0: error: Unsupported operand types for + ("None" and "int") [operator]
|
||||
src/documents/views/index.py:0: error: Argument "filename" to "FileResponse" has incompatible type "str | Any | None"; expected "str" [arg-type]
|
||||
src/documents/views/index.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/index.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/index.py:0: error: Item "AnonymousUser" of "User | AnonymousUser" has no attribute "get_full_name" [union-attr]
|
||||
src/documents/views/index.py:0: error: Item "None" of "Any | None" has no attribute "get" [union-attr]
|
||||
src/documents/views/index.py:0: error: Item "None" of "Any | None" has no attribute "get" [union-attr]
|
||||
src/documents/views/index.py:0: error: Item "None" of "ApplicationConfiguration | None" has no attribute "app_logo" [union-attr]
|
||||
src/documents/views/logs.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/logs.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Argument 1 to "int" has incompatible type "Any | Collection[str]"; expected "str | Buffer | SupportsInt | SupportsIndex" [arg-type]
|
||||
src/documents/views/metadata.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/metadata.py:0: error: Incompatible types in assignment (expression has type "tuple[type[IsAuthenticated], type[ViewDocumentsPermissions]]", variable has type "tuple[type[IsAuthenticated], type[PaperlessObjectPermissions]]") [assignment]
|
||||
src/documents/views/metadata.py:0: error: Need type annotation for "children_map" (hint: "children_map: dict[<type>, <type>] = ...") [var-annotated]
|
||||
src/documents/views/search.py:0: error: Argument 3 to "autocomplete" of "TantivyBackend" has incompatible type "User | AnonymousUser | None"; expected "AbstractUser | None" [arg-type]
|
||||
src/documents/views/search.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/search.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/search.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/search.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/search.py:0: error: Incompatible types in assignment (expression has type "QuerySet[Document, Document]", variable has type "list[Any]") [assignment]
|
||||
src/documents/views/search.py:0: error: Need type annotation for "docs" (hint: "docs: list[<type>] = ...") [var-annotated]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Any]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[CustomField]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Group]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[User]" is not indexable [index]
|
||||
src/documents/views/search.py:0: error: Value of type "Iterable[Workflow]" is not indexable [index]
|
||||
src/documents/views/sharing.py:0: error: "Sequence[_SupportsHasPermission]" has no attribute "append" [attr-defined]
|
||||
src/documents/views/sharing.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/sharing.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/sharing.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/sharing.py:0: error: Missing type arguments for generic type "GenericViewSet" [type-arg]
|
||||
src/documents/views/sharing.py:0: error: Need type annotation for "authentication_classes" (hint: "authentication_classes: list[<type>] = ...") [var-annotated]
|
||||
src/documents/views/sharing.py:0: error: Need type annotation for "permission_classes" (hint: "permission_classes: list[<type>] = ...") [var-annotated]
|
||||
src/documents/views/system.py:0: error: Argument 1 to "permitted_document_ids" has incompatible type "User | AnonymousUser"; expected "User | None" [arg-type]
|
||||
src/documents/views/system.py:0: error: Dict entry 0 has incompatible type "str": "bool"; expected "str": "str" [dict-item]
|
||||
src/documents/views/system.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/system.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/system.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/system.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "dict[Any, Any]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "bool", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "int", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "str | None", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, str]") [assignment]
|
||||
src/documents/views/system.py:0: error: Incompatible types in assignment (expression has type "type[DocumentSerializer]", variable has type "type[TrashSerializer]") [assignment]
|
||||
src/documents/views/system.py:0: error: Need type annotation for "ui_settings" (hint: "ui_settings: dict[<type>, <type>] = ...") [var-annotated]
|
||||
src/documents/views/tasks.py:0: error: "object" has no attribute "apply_async" [attr-defined]
|
||||
src/documents/views/tasks.py:0: error: Argument 1 to "TaskSummarySerializer" has incompatible type "QuerySet[PaperlessTask@AnnotatedWith[TypedDict({'total_count': int, 'pending_count': int, 'success_count': int, 'failure_count': int, 'avg_duration_seconds': Any, 'avg_wait_time_seconds': Any, 'last_run': Any, 'last_success': Any, 'last_failure': Any})], TypedDict({'task_type': str, 'total_count': Any, 'pending_count': Any, 'success_count': Any, 'failure_count': Any, 'avg_duration_seconds': Any, 'avg_wait_time_seconds': Any, 'last_run': Any, 'last_success': Any, 'last_failure': Any})]"; expected "dict[str, Any] | None" [arg-type]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/tasks.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/upload.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/workflows.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/views/workflows.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/workflows/actions.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
src/documents/workflows/actions.py:0: error: Function is missing a type annotation [no-untyped-def]
|
||||
src/documents/workflows/actions.py:0: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
||||
@@ -2145,9 +2145,9 @@ src/paperless_ai/ai_classifier.py:0: error: Argument 1 to "parse_ai_response" ha
|
||||
src/paperless_ai/ai_classifier.py:0: error: Incompatible types in assignment (expression has type "Any | None", variable has type "str") [assignment]
|
||||
src/paperless_ai/ai_classifier.py:0: error: Missing type arguments for generic type "dict" [type-arg]
|
||||
src/paperless_ai/ai_classifier.py:0: error: Missing type arguments for generic type "dict" [type-arg]
|
||||
src/paperless_ai/ai_classifier.py:0: error: TypedDict key must be a string literal; expected one of ("correspondents", "dates", "document_types", "storage_paths", "tags", ...) [literal-required]
|
||||
src/paperless_ai/ai_classifier.py:0: error: TypedDict key must be a string literal; expected one of ("correspondents", "dates", "document_types", "storage_paths", "tags", ...) [literal-required]
|
||||
src/paperless_ai/ai_classifier.py:0: error: TypedDict key must be a string literal; expected one of ("correspondents", "dates", "document_types", "storage_paths", "tags", ...) [literal-required]
|
||||
src/paperless_ai/ai_classifier.py:0: error: TypedDict key must be a string literal; expected one of ("title", "tags", "correspondents", "document_types", "storage_paths", ...) [literal-required]
|
||||
src/paperless_ai/ai_classifier.py:0: error: TypedDict key must be a string literal; expected one of ("title", "tags", "correspondents", "document_types", "storage_paths", ...) [literal-required]
|
||||
src/paperless_ai/ai_classifier.py:0: error: TypedDict key must be a string literal; expected one of ("title", "tags", "correspondents", "document_types", "storage_paths", ...) [literal-required]
|
||||
src/paperless_ai/base_model.py:0: error: Invalid index type "str | None" for "dict[str, FieldInfo]"; expected type "str" [index]
|
||||
src/paperless_ai/chat.py:0: error: Dict entry 1 has incompatible type "str": "str | Any | None"; expected "str": "int | str" [dict-item]
|
||||
src/paperless_ai/chat.py:0: error: Function is missing a return type annotation [no-untyped-def]
|
||||
|
||||
+357
-364
@@ -896,240 +896,233 @@
|
||||
"concise_description": "Argument `FieldRef | None` is not assignable to parameter `field` with type `FieldRef` in function `whoosh_compat.ast.Fuzzy.__init__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/search/_schema.py",
|
||||
"name": "unexpected-keyword",
|
||||
"concise_description": "Unexpected keyword argument `fast` in function `tantivy.tantivy.SchemaBuilder.add_json_field`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/base.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `MatchingModelSerializer.validate` overrides parent class `ModelSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 62,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/base.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "Cannot set item in `dict[str, QuerySet[User, User]]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/base.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `list` has no attribute `values_list`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/base.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `OwnedObjectListSerializer.to_representation` overrides parent class `ListSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/base.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `context`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 51,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/base.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `BaseSerializer[Unknown] | Field[Unknown, Unknown, Unknown, Unknown] | None` has no attribute `get_shared_object_pks`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 14,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "bad-assignment",
|
||||
"concise_description": "`ManyRelatedField | RelatedField[@_, @_, Any]` is not assignable to attribute `parent` with type `BaseSerializer[Unknown]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "Cannot set item in `Mapping[str, Any]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `TagSerializer.validate` overrides parent class `MatchingModelSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `type[CustomField.FieldDataType]` is not assignable to parameter `choices` with type `Sequence[Any]` in function `rest_framework.fields.ChoiceField.__init__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 28,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/base.py",
|
||||
"name": "bad-assignment",
|
||||
"concise_description": "`Unknown | None` is not assignable to attribute `method_name` with type `str`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 13,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `str` is not assignable to parameter `data_type` with type `CustomField.FieldDataType` in function `documents.models.CustomFieldInstance.get_value_field_name`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `CustomFieldInstanceSerializer.get_value` overrides parent class `ModelSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `CustomFieldInstanceSerializer.validate` overrides parent class `ModelSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 34,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "`None` is not subscriptable",
|
||||
"column": 7,
|
||||
"path": "src/documents/serialisers/bulk_edit.py",
|
||||
"name": "invalid-inheritance",
|
||||
"concise_description": "Class `BulkEditSerializer` has inconsistent type arguments for base class `Field`: `Field[Any, Any, Any, dict[str, Any]]` and `Field[Any, Any, Any, dict[str, list[int]]]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 30,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/documents.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "`None` is not subscriptable",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/documents.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `SearchResultListSerializer.to_representation` overrides parent class `ListSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 21,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `BaseSerializer[Unknown] | Field[Unknown, Unknown, Unknown, Unknown] | None` has no attribute `fetch_documents`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `context`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `context`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 51,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `BaseSerializer[Unknown] | Field[Unknown, Unknown, Unknown, Unknown] | None` has no attribute `get_shared_object_pks`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/documents.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `SearchResultSerializer.to_representation` overrides parent class `DocumentSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/documents.py",
|
||||
"name": "bad-override-mutable-attribute",
|
||||
"concise_description": "Class member `Meta.list_serializer_class` overrides parent class `Meta` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 14,
|
||||
"path": "src/documents/serialisers/metadata.py",
|
||||
"name": "bad-assignment",
|
||||
"concise_description": "`ManyRelatedField | RelatedField[@_, @_, Any]` is not assignable to attribute `parent` with type `BaseSerializer[Unknown]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/serialisers/metadata.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "Cannot set item in `Mapping[str, Any]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers/metadata.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `TagSerializer.validate` overrides parent class `MatchingModelSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/serialisers/metadata.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `type[CustomField.FieldDataType]` is not assignable to parameter `choices` with type `Sequence[Any]` in function `rest_framework.fields.ChoiceField.__init__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 13,
|
||||
"path": "src/documents/serialisers/metadata.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `str` is not assignable to parameter `data_type` with type `CustomField.FieldDataType` in function `documents.models.CustomFieldInstance.get_value_field_name`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers/metadata.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `CustomFieldInstanceSerializer.get_value` overrides parent class `ModelSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers/metadata.py",
|
||||
"name": "bad-override-param-name",
|
||||
"concise_description": "Class member `CustomFieldInstanceSerializer.validate` overrides parent class `ModelSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 34,
|
||||
"path": "src/documents/serialisers/metadata.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "`None` is not subscriptable",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 21,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/saved_views.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "`Literal[SavedView.DisplayFields.CUSTOM_FIELD]` is not subscriptable",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 36,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/saved_views.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "`None` is not subscriptable",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 7,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"name": "invalid-inheritance",
|
||||
"concise_description": "Class `BulkEditSerializer` has inconsistent type arguments for base class `Field`: `Field[Any, Any, Any, dict[str, Any]]` and `Field[Any, Any, Any, dict[str, list[int]]]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 73,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/sharing.py",
|
||||
"name": "unbound-name",
|
||||
"concise_description": "`address` is uninitialized",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/system.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `UiSettingsViewSerializer.create` overrides parent class `ModelSerializer` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 46,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/tasks.py",
|
||||
"name": "no-matching-overload",
|
||||
"concise_description": "No matching overload found for function `dict.get` called with arguments: (str, str)",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 38,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/tasks.py",
|
||||
"name": "no-matching-overload",
|
||||
"concise_description": "No matching overload found for function `dict.get` called with arguments: (str, str)",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 51,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/tasks.py",
|
||||
"name": "no-matching-overload",
|
||||
"concise_description": "No matching overload found for function `dict.get` called with arguments: (str, Literal['manual_task'])",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/workflows.py",
|
||||
"name": "unbound-name",
|
||||
"concise_description": "`triggers` may be uninitialized",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 62,
|
||||
"path": "src/documents/serialisers.py",
|
||||
"path": "src/documents/serialisers/workflows.py",
|
||||
"name": "unbound-name",
|
||||
"concise_description": "`actions` may be uninitialized",
|
||||
"severity": "error"
|
||||
@@ -3619,389 +3612,389 @@
|
||||
"concise_description": "`float | int | None` is not assignable to attribute `MAX_IMAGE_PIXELS` with type `int | None`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 31,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `AbstractBaseUser` has no attribute `username`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 32,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `AbstractBaseUser | AnonymousUser` has no attribute `get_full_name`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/base.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `BulkPermissionMixin` has no attribute `queryset`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 19,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/base.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `object` has no attribute `get_serializer_context`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 24,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/base.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `BulkPermissionMixin` has no attribute `filter_queryset`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 45,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/base.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `BulkPermissionMixin` has no attribute `get_queryset`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 22,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/base.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `BulkPermissionMixin` has no attribute `queryset`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 29,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `Self@CorrespondentViewSet` is not assignable to parameter `instance` with type `Options[Any] | None` in function `django.db.models.manager.BaseManager.__get__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 29,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `annotate`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 25,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `Self@CorrespondentViewSet` is not assignable to parameter `instance` with type `Options[Any] | None` in function `django.db.models.manager.BaseManager.__get__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 25,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `annotate`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 48,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `Correspondent` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 48,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `DocumentType` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 48,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `StoragePath` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 28,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Class `DocumentFilterSet` has no class attribute `declared_filters`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `DocumentViewSet.destroy` overrides parent class `DestroyModelMixin` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 37,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `list[MetadataEntry] | list[Unknown] | None` is not assignable to parameter `original_metadata` with type `list[Unknown]` in function `documents.caching.set_metadata_cache`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 57,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `DocumentClassifier | None` is not assignable to parameter `classifier` with type `DocumentClassifier` in function `documents.matching.match_correspondents`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `DocumentClassifier | None` is not assignable to parameter `classifier` with type `DocumentClassifier` in function `documents.matching.match_tags`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 59,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `DocumentClassifier | None` is not assignable to parameter `classifier` with type `DocumentClassifier` in function `documents.matching.match_document_types`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 58,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `DocumentClassifier | None` is not assignable to parameter `classifier` with type `DocumentClassifier` in function `documents.matching.match_storage_paths`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `ClassificationSuggestions` is not assignable to parameter `suggestions` with type `dict[Unknown, Unknown]` in function `documents.caching.set_llm_suggestions_cache`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 5,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-specialization",
|
||||
"concise_description": "`(self: Self@DocumentViewSet, request: Unknown, pk: Unknown | None = None) -> HttpResponseForbidden | Response | None` is not assignable to upper bound `(...) -> HttpResponseBase` of type variable `_View`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 36,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-argument",
|
||||
"concise_description": "Missing argument `request` in function `DocumentViewSet.email_documents`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `UnifiedSearchViewSet.list` overrides parent class `DocumentViewSet` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `BasePagination | None` has no attribute `get_page_size`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 58,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `BasePagination | None` has no attribute `page_size`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 13,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "not-iterable",
|
||||
"concise_description": "Type `None` is not iterable",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 43,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `TantivyRelevanceList` is not assignable to parameter `queryset` with type `QuerySet[Any, @_] | Sequence[@_]` in function `rest_framework.generics.GenericAPIView.paginate_queryset`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 25,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "`+` is not supported between `None` and `Literal[1]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/base.py",
|
||||
"name": "not-iterable",
|
||||
"concise_description": "Type `None` is not iterable",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 18,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/base.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser` is not assignable to parameter `user` with type `User` in function `DocumentSelectionMixin._resolve_document_ids`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 18,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/base.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser` is not assignable to parameter `user` with type `User` in function `DocumentOperationPermissionMixin._has_document_permissions`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 18,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/bulk_edit.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser` is not assignable to parameter `user` with type `User` in function `DocumentSelectionMixin._resolve_document_ids`",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser` is not assignable to parameter `user` with type `User` in function `documents.views.base.DocumentSelectionMixin._resolve_document_ids`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 18,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/bulk_edit.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser` is not assignable to parameter `user` with type `User` in function `DocumentOperationPermissionMixin._has_document_permissions`",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser` is not assignable to parameter `user` with type `User` in function `documents.views.base.DocumentOperationPermissionMixin._has_document_permissions`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 33,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/bulk_edit.py",
|
||||
"name": "unbound-name",
|
||||
"concise_description": "`old_values` may be uninitialized",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `Correspondent` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `Tag` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `DocumentType` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `StoragePath` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `CustomField` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 65,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser | None` is not assignable to parameter `user` with type `AbstractUser | None` in function `documents.search._backend.TantivyBackend.autocomplete`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `TasksViewSet.get_serializer_class` overrides parent class `ReadOnlyModelViewSet` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 12,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `AbstractBaseUser` has no attribute `is_staff`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 44,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `QuerySet[PaperlessTask, dict[str, Any]]` is not assignable to parameter `instance` with type `dict[str, Any] | None` in function `rest_framework.serializers.BaseSerializer.__init__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 13,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `Sequence` has no attribute `append`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 24,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/bulk_edit.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `BaseSerializer` has no attribute `get_object_class`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 45,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/bulk_edit.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser` is not assignable to parameter `user` with type `User | None` in function `documents.permissions.permitted_object_ids`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 16,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/bulk_edit.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `AbstractBaseUser` has no attribute `is_superuser`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/bulk_edit.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `AbstractBaseUser` has no attribute `has_perm`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/views.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `WorkflowTriggerViewSet.partial_update` overrides parent class `ModelViewSet` in an inconsistent manner",
|
||||
"column": 48,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `Correspondent` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 48,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `DocumentType` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 48,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `StoragePath` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 28,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Class `DocumentFilterSet` has no class attribute `declared_filters`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `WorkflowActionViewSet.partial_update` overrides parent class `ModelViewSet` in an inconsistent manner",
|
||||
"concise_description": "Class member `DocumentViewSet.destroy` overrides parent class `DestroyModelMixin` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 37,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `list[MetadataEntry] | list[Unknown] | None` is not assignable to parameter `original_metadata` with type `list[Unknown]` in function `documents.caching.set_metadata_cache`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 57,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `DocumentClassifier | None` is not assignable to parameter `classifier` with type `DocumentClassifier` in function `documents.matching.match_correspondents`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `DocumentClassifier | None` is not assignable to parameter `classifier` with type `DocumentClassifier` in function `documents.matching.match_tags`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 59,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `DocumentClassifier | None` is not assignable to parameter `classifier` with type `DocumentClassifier` in function `documents.matching.match_document_types`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 58,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `DocumentClassifier | None` is not assignable to parameter `classifier` with type `DocumentClassifier` in function `documents.matching.match_storage_paths`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `ClassificationSuggestions` is not assignable to parameter `suggestions` with type `dict[Unknown, Unknown]` in function `documents.caching.set_llm_suggestions_cache`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 5,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-specialization",
|
||||
"concise_description": "`(self: Self@DocumentViewSet, request: Unknown, pk: Unknown | None = None) -> HttpResponseForbidden | Response | None` is not assignable to upper bound `(...) -> HttpResponseBase` of type variable `_View`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 36,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "missing-argument",
|
||||
"concise_description": "Missing argument `request` in function `DocumentViewSet.email_documents`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `UnifiedSearchViewSet.list` overrides parent class `DocumentViewSet` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `BasePagination | None` has no attribute `get_page_size`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 58,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `BasePagination | None` has no attribute `page_size`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 13,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "not-iterable",
|
||||
"concise_description": "Type `None` is not iterable",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 43,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `TantivyRelevanceList` is not assignable to parameter `queryset` with type `QuerySet[Any, @_] | Sequence[@_]` in function `rest_framework.generics.GenericAPIView.paginate_queryset`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 25,
|
||||
"path": "src/documents/views/documents.py",
|
||||
"name": "unsupported-operation",
|
||||
"concise_description": "`+` is not supported between `None` and `Literal[1]`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 31,
|
||||
"path": "src/documents/views/index.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `AbstractBaseUser` has no attribute `username`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 32,
|
||||
"path": "src/documents/views/index.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of type `AbstractBaseUser | AnonymousUser` has no attribute `get_full_name`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 16,
|
||||
"path": "src/documents/views/index.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `app_logo`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 29,
|
||||
"path": "src/documents/views/metadata.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `Self@CorrespondentViewSet` is not assignable to parameter `instance` with type `Options[Any] | None` in function `django.db.models.manager.BaseManager.__get__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 29,
|
||||
"path": "src/documents/views/metadata.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `annotate`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 25,
|
||||
"path": "src/documents/views/metadata.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `Self@CorrespondentViewSet` is not assignable to parameter `instance` with type `Options[Any] | None` in function `django.db.models.manager.BaseManager.__get__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 25,
|
||||
"path": "src/documents/views/metadata.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `annotate`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views/search.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `Correspondent` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views/search.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `Tag` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views/search.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `DocumentType` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views/search.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `StoragePath` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 52,
|
||||
"path": "src/documents/views/search.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `CustomField` has no attribute `document_count`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 65,
|
||||
"path": "src/documents/views/search.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser | None` is not assignable to parameter `user` with type `AbstractUser | None` in function `documents.search._backend.TantivyBackend.autocomplete`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 13,
|
||||
"path": "src/documents/views/sharing.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `Sequence` has no attribute `append`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 40,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/system.py",
|
||||
"name": "unbound-name",
|
||||
"concise_description": "`all_migrations` may be uninitialized",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 17,
|
||||
"path": "src/documents/views.py",
|
||||
"path": "src/documents/views/system.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `AbstractBaseUser | AnonymousUser` is not assignable to parameter `user` with type `User | None` in function `documents.permissions.permitted_document_ids`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 16,
|
||||
"path": "src/documents/views.py",
|
||||
"column": 9,
|
||||
"path": "src/documents/views/tasks.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `TasksViewSet.get_serializer_class` overrides parent class `ReadOnlyModelViewSet` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 12,
|
||||
"path": "src/documents/views/tasks.py",
|
||||
"name": "missing-attribute",
|
||||
"concise_description": "Object of class `NoneType` has no attribute `app_logo`",
|
||||
"concise_description": "Object of class `AbstractBaseUser` has no attribute `is_staff`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 44,
|
||||
"path": "src/documents/views/tasks.py",
|
||||
"name": "bad-argument-type",
|
||||
"concise_description": "Argument `QuerySet[PaperlessTask, dict[str, Any]]` is not assignable to parameter `instance` with type `dict[str, Any] | None` in function `rest_framework.serializers.BaseSerializer.__init__`",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/views/workflows.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `WorkflowTriggerViewSet.partial_update` overrides parent class `ModelViewSet` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"column": 9,
|
||||
"path": "src/documents/views/workflows.py",
|
||||
"name": "bad-override",
|
||||
"concise_description": "Class member `WorkflowActionViewSet.partial_update` overrides parent class `ModelViewSet` in an inconsistent manner",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ Paperless-ngx is a document management system that transforms your physical docu
|
||||
|
||||
Paperless-ngx is the official successor to the original [Paperless](https://github.com/the-paperless-project/paperless) & [Paperless-ng](https://github.com/jonaswinkler/paperless-ng) projects and is designed to distribute the responsibility of advancing and supporting the project among a team of people. [Consider joining us!](#community-support)
|
||||
|
||||
Thanks to the generous folks at [Fyra Stack](https://fyrastack.com), a demo is available at [demo.paperless-ngx.com](https://demo.paperless-ngx.com) using login `demo` / `demo`. _Note: demo content is reset frequently and confidential information should not be uploaded._
|
||||
Thanks to the generous folks at [DigitalOcean](https://m.do.co/c/8d70b916d462), a demo is available at [demo.paperless-ngx.com](https://demo.paperless-ngx.com) using login `demo` / `demo`. _Note: demo content is reset frequently and confidential information should not be uploaded._
|
||||
|
||||
- [Features](#features)
|
||||
- [Getting started](#getting-started)
|
||||
@@ -33,9 +33,13 @@ Thanks to the generous folks at [Fyra Stack](https://fyrastack.com), a demo is a
|
||||
- [Related Projects](#related-projects)
|
||||
- [Important Note](#important-note)
|
||||
|
||||
<p align="right">Demo hosting provided by:<br/>
|
||||
<a href="https://fyrastack.com">
|
||||
<img src="docs/assets/sponsors/fyra-stack.svg" alt="" width="28px" align="absmiddle"> Fyra Stack
|
||||
<p align="right">This project is supported by:<br/>
|
||||
<a href="https://m.do.co/c/8d70b916d462" style="padding-top: 4px; display: block;">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_white.svg" width="140px">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="140px">
|
||||
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_black_.svg" width="140px">
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ services:
|
||||
volumes:
|
||||
- dbdata:/var/lib/mysql
|
||||
environment:
|
||||
MARIADB_HOST: paperless
|
||||
MARIADB_DATABASE: paperless
|
||||
MARIADB_USER: paperless
|
||||
MARIADB_PASSWORD: paperless
|
||||
|
||||
@@ -36,6 +36,7 @@ services:
|
||||
volumes:
|
||||
- dbdata:/var/lib/mysql
|
||||
environment:
|
||||
MARIADB_HOST: paperless
|
||||
MARIADB_DATABASE: paperless
|
||||
MARIADB_USER: paperless
|
||||
MARIADB_PASSWORD: paperless
|
||||
|
||||
@@ -1010,19 +1010,6 @@ documents to both separate and categorize them in a single operation.
|
||||
**Example:** A 6-page scan with TAG:invoice on page 3 and TAG:receipt on page 5 will create
|
||||
three documents: pages 1-2 (no tags), pages 3-4 (tagged "invoice"), and pages 5-6 (tagged "receipt").
|
||||
|
||||
### Barcode Contents {#barcode-contents}
|
||||
|
||||
By default, Paperless only uses barcodes for splitting, ASNs and tags. With
|
||||
[`PAPERLESS_CONSUMER_STORE_BARCODE_VALUES`](configuration.md#PAPERLESS_CONSUMER_STORE_BARCODE_VALUES)
|
||||
enabled, it stores the content of every barcode with the document, e.g. payment codes or QR codes.
|
||||
|
||||
- Barcodes are listed on the **Metadata** tab with page, type and content, and can be copied.
|
||||
- The API returns them in the `barcodes` field of `/api/documents/{id}/metadata/`.
|
||||
- They can be [searched](usage.md#searching-barcodes), e.g. `barcodes:DE89370400440532013000`.
|
||||
- Only the first [`PAPERLESS_CONSUMER_BARCODE_MAX_PAGES`](configuration.md#PAPERLESS_CONSUMER_BARCODE_MAX_PAGES)
|
||||
pages are scanned. Reprocessing reads the barcodes of existing documents.
|
||||
- Each version keeps its own barcodes, and the newest version's are shown and searched.
|
||||
|
||||
## Automatic collation of double-sided documents {#collate}
|
||||
|
||||
!!! note
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="666.667" height="666.667" viewBox="0 0 666.667 666.667"><g stroke-width="1.333"><path fill="#fef400" d="m332.66668 418.66668h-84.66667v-85.33334-85.33333h84.66667 84.66667v-85.33334-85.333334h85.33333 85.33334v85.333334 85.33334h-85.33334-85.33333v85.33333 85.33334z"/><path fill="#fe6565" d="m248.00001 589.33335h-170.666674v-170.66667-170.66667h85.333334 85.33334v-85.33334-85.333334h84.66667 84.66667v85.333334 85.33334h85.33333 85.33334v85.33333 85.33334h-84.66667-84.66667v85.33334 85.33333zm84.66667-170.66667h84.66667v-85.33334-85.33333h-84.66667-84.66667v85.33333 85.33334z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 641 B |
@@ -1,130 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## paperless-ngx 3.3.0
|
||||
|
||||
### Features / Enhancements
|
||||
|
||||
- Enhancement: more control over suggestion requests [@shamoon](https://github.com/shamoon) ([#14258](https://github.com/paperless-ngx/paperless-ngx/pull/14258))
|
||||
- Chorehancement: set manifest CORS for credentials [@shamoon](https://github.com/shamoon) ([#14307](https://github.com/paperless-ngx/paperless-ngx/pull/14307))
|
||||
- Enhancement: include Django admin with 2FA [@shamoon](https://github.com/shamoon) ([#14270](https://github.com/paperless-ngx/paperless-ngx/pull/14270))
|
||||
- Feature: propagate resolved secrets to interactive container shells [@stumpylog](https://github.com/stumpylog) ([#14254](https://github.com/paperless-ngx/paperless-ngx/pull/14254))
|
||||
- Enhancement: support separate embedding API key [@furkanural](https://github.com/furkanural) ([#14067](https://github.com/paperless-ngx/paperless-ngx/pull/14067))
|
||||
- Enhancement: support passthrough extra params for LLMs [@shamoon](https://github.com/shamoon) ([#14202](https://github.com/paperless-ngx/paperless-ngx/pull/14202))
|
||||
- Feature: store barcode contents, list and search them [@jurassicparkicecream](https://github.com/jurassicparkicecream) ([#14276](https://github.com/paperless-ngx/paperless-ngx/pull/14276))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fix: Set the ProcessedMail owner based on the rule owner in all cases [@stumpylog](https://github.com/stumpylog) ([#14356](https://github.com/paperless-ngx/paperless-ngx/pull/14356))
|
||||
- Fix: Ensure log rotation settings are converted to integers [@stumpylog](https://github.com/stumpylog) ([#14343](https://github.com/paperless-ngx/paperless-ngx/pull/14343))
|
||||
- Fix: Wrap apt calls into a retry so we can ideally jump a slow mirror [@stumpylog](https://github.com/stumpylog) ([#14344](https://github.com/paperless-ngx/paperless-ngx/pull/14344))
|
||||
- Fix: ship pdf.js CMaps so CJK documents render in the viewer [@MrOggy85](https://github.com/MrOggy85) ([#14318](https://github.com/paperless-ngx/paperless-ngx/pull/14318))
|
||||
- Fix: use version page\_count for versioned document [@shamoon](https://github.com/shamoon) ([#14280](https://github.com/paperless-ngx/paperless-ngx/pull/14280))
|
||||
- Fix: allow pointer events for pdf links in pngx viewer [@shamoon](https://github.com/shamoon) ([#14264](https://github.com/paperless-ngx/paperless-ngx/pull/14264))
|
||||
- Fix: During a move to the trash directory, only attempt to copy metadata [@stumpylog](https://github.com/stumpylog) ([#14250](https://github.com/paperless-ngx/paperless-ngx/pull/14250))
|
||||
- Fix: convert file mtime to the configured time zone directly [@stumpylog](https://github.com/stumpylog) ([#14249](https://github.com/paperless-ngx/paperless-ngx/pull/14249))
|
||||
- Fix: ensure documentDeleted subscription is discarded [@shamoon](https://github.com/shamoon) ([#14247](https://github.com/paperless-ngx/paperless-ngx/pull/14247))
|
||||
- Chore: Fix bugs in the test suite [@stumpylog](https://github.com/stumpylog) ([#14244](https://github.com/paperless-ngx/paperless-ngx/pull/14244))
|
||||
- Fix: ensure bulk operations are checked against version root [@shamoon](https://github.com/shamoon) ([#14246](https://github.com/paperless-ngx/paperless-ngx/pull/14246))
|
||||
- Fix: indexing after document-added workflows signal [@shamoon](https://github.com/shamoon) ([#14242](https://github.com/paperless-ngx/paperless-ngx/pull/14242))
|
||||
- Fix: Record full tag and custom field lists in bulk edit audit log [@stumpylog](https://github.com/stumpylog) ([#14236](https://github.com/paperless-ngx/paperless-ngx/pull/14236))
|
||||
- Chore: update pikepdf for ocrmypdf requirement [@shamoon](https://github.com/shamoon) ([#14235](https://github.com/paperless-ngx/paperless-ngx/pull/14235))
|
||||
- Fix: handle legacy bulk edit split page range with missing page\_count [@shamoon](https://github.com/shamoon) ([#14212](https://github.com/paperless-ngx/paperless-ngx/pull/14212))
|
||||
- Fix: ignore invalid EXIF orientation when generating image archives [@zhzy0077](https://github.com/zhzy0077) ([#14203](https://github.com/paperless-ngx/paperless-ngx/pull/14203))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Documentation: correct duplicates info [@shamoon](https://github.com/shamoon) ([#14243](https://github.com/paperless-ngx/paperless-ngx/pull/14243))
|
||||
|
||||
### Maintenance
|
||||
|
||||
- Chore(deps): Bump the actions group across 1 directory with 4 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14332](https://github.com/paperless-ngx/paperless-ngx/pull/14332))
|
||||
- Fix: Wrap apt calls into a retry so we can ideally jump a slow mirror [@stumpylog](https://github.com/stumpylog) ([#14344](https://github.com/paperless-ngx/paperless-ngx/pull/14344))
|
||||
- Chore(deps): Bump the actions group across 1 directory with 10 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14301](https://github.com/paperless-ngx/paperless-ngx/pull/14301))
|
||||
|
||||
### Dependencies
|
||||
|
||||
<details>
|
||||
<summary>27 changes</summary>
|
||||
|
||||
- Chore(deps): Bump django-filter from 25.2 to 26.1 @[dependabot[bot]](https://github.com/apps/dependabot) ([#14337](https://github.com/paperless-ngx/paperless-ngx/pull/14337))
|
||||
- Chore(deps): Bump the utilities-patch group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14338](https://github.com/paperless-ngx/paperless-ngx/pull/14338))
|
||||
- Chore(deps): Bump the pre-commit-dependencies group across 1 directory with 3 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14351](https://github.com/paperless-ngx/paperless-ngx/pull/14351))
|
||||
- Chore(deps-dev): Bump types-channels from 4.3.0.20260408 to 4.3.0.20260518 @[dependabot[bot]](https://github.com/apps/dependabot) ([#14335](https://github.com/paperless-ngx/paperless-ngx/pull/14335))
|
||||
- docker(deps): Bump astral-sh/uv from 0.12.20-python3.14-trixie-slim to 0.12.23-python3.14-trixie-slim @[dependabot[bot]](https://github.com/apps/dependabot) ([#14327](https://github.com/paperless-ngx/paperless-ngx/pull/14327))
|
||||
- Chore(deps): Bump the actions group across 1 directory with 4 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14332](https://github.com/paperless-ngx/paperless-ngx/pull/14332))
|
||||
- Chore(deps): Bump the uv group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14325](https://github.com/paperless-ngx/paperless-ngx/pull/14325))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group across 1 directory with 13 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14329](https://github.com/paperless-ngx/paperless-ngx/pull/14329))
|
||||
- Chore(deps-dev): Bump prettier from 3.9.8 to 3.9.9 in /src-ui @[dependabot[bot]](https://github.com/apps/dependabot) ([#14331](https://github.com/paperless-ngx/paperless-ngx/pull/14331))
|
||||
- Chore(deps-dev): Bump the frontend-eslint-dependencies group across 1 directory with 3 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14330](https://github.com/paperless-ngx/paperless-ngx/pull/14330))
|
||||
- Chore(deps-dev): Bump zensical from 0.0.64 to 0.0.65 in the development group @[dependabot[bot]](https://github.com/apps/dependabot) ([#14326](https://github.com/paperless-ngx/paperless-ngx/pull/14326))
|
||||
- Chore(deps): Bump the uv group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14314](https://github.com/paperless-ngx/paperless-ngx/pull/14314))
|
||||
- Chore(deps): Bump the utilities-minor group across 1 directory with 7 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14305](https://github.com/paperless-ngx/paperless-ngx/pull/14305))
|
||||
- docker-compose(deps): bump greenmail/standalone from 2.1.13 to 2.1.14 in /docker/compose @[dependabot[bot]](https://github.com/apps/dependabot) ([#14281](https://github.com/paperless-ngx/paperless-ngx/pull/14281))
|
||||
- docker(deps): Bump astral-sh/uv from 0.12.16-python3.14-trixie-slim to 0.12.20-python3.14-trixie-slim @[dependabot[bot]](https://github.com/apps/dependabot) ([#14282](https://github.com/paperless-ngx/paperless-ngx/pull/14282))
|
||||
- Chore(deps): Bump the pre-commit-dependencies group across 1 directory with 3 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14283](https://github.com/paperless-ngx/paperless-ngx/pull/14283))
|
||||
- Chore(deps): Bump the utilities-patch group across 1 directory with 6 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14297](https://github.com/paperless-ngx/paperless-ngx/pull/14297))
|
||||
- Chore(deps): Bump the actions group across 1 directory with 10 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14301](https://github.com/paperless-ngx/paperless-ngx/pull/14301))
|
||||
- Chore(deps-dev): Bump the frontend-jest-dependencies group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14286](https://github.com/paperless-ngx/paperless-ngx/pull/14286))
|
||||
- Chore(deps-dev): Bump eslint from 10.10.0 to 10.11.0 in /src-ui in the frontend-eslint-dependencies group across 1 directory @[dependabot[bot]](https://github.com/apps/dependabot) ([#14287](https://github.com/paperless-ngx/paperless-ngx/pull/14287))
|
||||
- Chore(deps-dev): Bump @types/node from 26.5.0 to 26.6.2 in /src-ui @[dependabot[bot]](https://github.com/apps/dependabot) ([#14288](https://github.com/paperless-ngx/paperless-ngx/pull/14288))
|
||||
- Chore(deps-dev): Bump prettier from 3.9.6 to 3.9.8 in /src-ui @[dependabot[bot]](https://github.com/apps/dependabot) ([#14289](https://github.com/paperless-ngx/paperless-ngx/pull/14289))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group across 1 directory with 10 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14285](https://github.com/paperless-ngx/paperless-ngx/pull/14285))
|
||||
- Chore: replace bleach with turbohtml [@gaborbernat](https://github.com/gaborbernat) ([#14269](https://github.com/paperless-ngx/paperless-ngx/pull/14269))
|
||||
- Chore(deps): Bump autobahn from 25.12.2 to 26.7.1 in the uv group across 1 directory @[dependabot[bot]](https://github.com/apps/dependabot) ([#14231](https://github.com/paperless-ngx/paperless-ngx/pull/14231))
|
||||
- Chore: update pikepdf for ocrmypdf requirement [@shamoon](https://github.com/shamoon) ([#14235](https://github.com/paperless-ngx/paperless-ngx/pull/14235))
|
||||
- Chore(deps): Bump the pre-commit-dependencies group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14133](https://github.com/paperless-ngx/paperless-ngx/pull/14133))
|
||||
|
||||
</details>
|
||||
|
||||
### All App Changes
|
||||
|
||||
<details>
|
||||
<summary>41 changes</summary>
|
||||
|
||||
- Feature: store barcode contents, list and search them [@jurassicparkicecream](https://github.com/jurassicparkicecream) ([#14276](https://github.com/paperless-ngx/paperless-ngx/pull/14276))
|
||||
- Fix: Set the ProcessedMail owner based on the rule owner in all cases [@stumpylog](https://github.com/stumpylog) ([#14356](https://github.com/paperless-ngx/paperless-ngx/pull/14356))
|
||||
- Chore(deps): Bump django-filter from 25.2 to 26.1 @[dependabot[bot]](https://github.com/apps/dependabot) ([#14337](https://github.com/paperless-ngx/paperless-ngx/pull/14337))
|
||||
- Chore(deps): Bump the utilities-patch group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14338](https://github.com/paperless-ngx/paperless-ngx/pull/14338))
|
||||
- Chore(deps-dev): Bump types-channels from 4.3.0.20260408 to 4.3.0.20260518 @[dependabot[bot]](https://github.com/apps/dependabot) ([#14335](https://github.com/paperless-ngx/paperless-ngx/pull/14335))
|
||||
- Chore(deps): Bump the uv group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14325](https://github.com/paperless-ngx/paperless-ngx/pull/14325))
|
||||
- Fix: Ensure log rotation settings are converted to integers [@stumpylog](https://github.com/stumpylog) ([#14343](https://github.com/paperless-ngx/paperless-ngx/pull/14343))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group across 1 directory with 13 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14329](https://github.com/paperless-ngx/paperless-ngx/pull/14329))
|
||||
- Chore(deps-dev): Bump prettier from 3.9.8 to 3.9.9 in /src-ui @[dependabot[bot]](https://github.com/apps/dependabot) ([#14331](https://github.com/paperless-ngx/paperless-ngx/pull/14331))
|
||||
- Chore(deps-dev): Bump the frontend-eslint-dependencies group across 1 directory with 3 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14330](https://github.com/paperless-ngx/paperless-ngx/pull/14330))
|
||||
- Fix: ship pdf.js CMaps so CJK documents render in the viewer [@MrOggy85](https://github.com/MrOggy85) ([#14318](https://github.com/paperless-ngx/paperless-ngx/pull/14318))
|
||||
- Chore(deps-dev): Bump zensical from 0.0.64 to 0.0.65 in the development group @[dependabot[bot]](https://github.com/apps/dependabot) ([#14326](https://github.com/paperless-ngx/paperless-ngx/pull/14326))
|
||||
- Enhancement: more control over suggestion requests [@shamoon](https://github.com/shamoon) ([#14258](https://github.com/paperless-ngx/paperless-ngx/pull/14258))
|
||||
- Chore(deps): Bump the uv group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14314](https://github.com/paperless-ngx/paperless-ngx/pull/14314))
|
||||
- Chore: anchor admin url pattern [@shamoon](https://github.com/shamoon) ([#14316](https://github.com/paperless-ngx/paperless-ngx/pull/14316))
|
||||
- Chorehancement: set manifest CORS for credentials [@shamoon](https://github.com/shamoon) ([#14307](https://github.com/paperless-ngx/paperless-ngx/pull/14307))
|
||||
- Chore(deps): Bump the utilities-minor group across 1 directory with 7 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14305](https://github.com/paperless-ngx/paperless-ngx/pull/14305))
|
||||
- Chore(deps): Bump the utilities-patch group across 1 directory with 6 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14297](https://github.com/paperless-ngx/paperless-ngx/pull/14297))
|
||||
- Chore(deps-dev): Bump the frontend-jest-dependencies group across 1 directory with 2 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14286](https://github.com/paperless-ngx/paperless-ngx/pull/14286))
|
||||
- Chore(deps-dev): Bump eslint from 10.10.0 to 10.11.0 in /src-ui in the frontend-eslint-dependencies group across 1 directory @[dependabot[bot]](https://github.com/apps/dependabot) ([#14287](https://github.com/paperless-ngx/paperless-ngx/pull/14287))
|
||||
- Chore(deps-dev): Bump @types/node from 26.5.0 to 26.6.2 in /src-ui @[dependabot[bot]](https://github.com/apps/dependabot) ([#14288](https://github.com/paperless-ngx/paperless-ngx/pull/14288))
|
||||
- Chore(deps-dev): Bump prettier from 3.9.6 to 3.9.8 in /src-ui @[dependabot[bot]](https://github.com/apps/dependabot) ([#14289](https://github.com/paperless-ngx/paperless-ngx/pull/14289))
|
||||
- Chore(deps): Bump the frontend-angular-dependencies group across 1 directory with 10 updates @[dependabot[bot]](https://github.com/apps/dependabot) ([#14285](https://github.com/paperless-ngx/paperless-ngx/pull/14285))
|
||||
- Fix: use version page\_count for versioned document [@shamoon](https://github.com/shamoon) ([#14280](https://github.com/paperless-ngx/paperless-ngx/pull/14280))
|
||||
- Chore: replace bleach with turbohtml [@gaborbernat](https://github.com/gaborbernat) ([#14269](https://github.com/paperless-ngx/paperless-ngx/pull/14269))
|
||||
- Enhancement: include Django admin with 2FA [@shamoon](https://github.com/shamoon) ([#14270](https://github.com/paperless-ngx/paperless-ngx/pull/14270))
|
||||
- Fix: allow pointer events for pdf links in pngx viewer [@shamoon](https://github.com/shamoon) ([#14264](https://github.com/paperless-ngx/paperless-ngx/pull/14264))
|
||||
- Feature: propagate resolved secrets to interactive container shells [@stumpylog](https://github.com/stumpylog) ([#14254](https://github.com/paperless-ngx/paperless-ngx/pull/14254))
|
||||
- Fix: During a move to the trash directory, only attempt to copy metadata [@stumpylog](https://github.com/stumpylog) ([#14250](https://github.com/paperless-ngx/paperless-ngx/pull/14250))
|
||||
- Fix: convert file mtime to the configured time zone directly [@stumpylog](https://github.com/stumpylog) ([#14249](https://github.com/paperless-ngx/paperless-ngx/pull/14249))
|
||||
- Fix: ensure documentDeleted subscription is discarded [@shamoon](https://github.com/shamoon) ([#14247](https://github.com/paperless-ngx/paperless-ngx/pull/14247))
|
||||
- Chore: Fix bugs in the test suite [@stumpylog](https://github.com/stumpylog) ([#14244](https://github.com/paperless-ngx/paperless-ngx/pull/14244))
|
||||
- Fix: ensure bulk operations are checked against version root [@shamoon](https://github.com/shamoon) ([#14246](https://github.com/paperless-ngx/paperless-ngx/pull/14246))
|
||||
- Enhancement: support separate embedding API key [@furkanural](https://github.com/furkanural) ([#14067](https://github.com/paperless-ngx/paperless-ngx/pull/14067))
|
||||
- Enhancement: support passthrough extra params for LLMs [@shamoon](https://github.com/shamoon) ([#14202](https://github.com/paperless-ngx/paperless-ngx/pull/14202))
|
||||
- Chore(deps): Bump autobahn from 25.12.2 to 26.7.1 in the uv group across 1 directory @[dependabot[bot]](https://github.com/apps/dependabot) ([#14231](https://github.com/paperless-ngx/paperless-ngx/pull/14231))
|
||||
- Fix: indexing after document-added workflows signal [@shamoon](https://github.com/shamoon) ([#14242](https://github.com/paperless-ngx/paperless-ngx/pull/14242))
|
||||
- Fix: Record full tag and custom field lists in bulk edit audit log [@stumpylog](https://github.com/stumpylog) ([#14236](https://github.com/paperless-ngx/paperless-ngx/pull/14236))
|
||||
- Chore: update pikepdf for ocrmypdf requirement [@shamoon](https://github.com/shamoon) ([#14235](https://github.com/paperless-ngx/paperless-ngx/pull/14235))
|
||||
- Fix: handle legacy bulk edit split page range with missing page\_count [@shamoon](https://github.com/shamoon) ([#14212](https://github.com/paperless-ngx/paperless-ngx/pull/14212))
|
||||
- Fix: ignore invalid EXIF orientation when generating image archives [@zhzy0077](https://github.com/zhzy0077) ([#14203](https://github.com/paperless-ngx/paperless-ngx/pull/14203))
|
||||
|
||||
</details>
|
||||
|
||||
## paperless-ngx 3.2.1
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1796,13 +1796,6 @@ assigns or creates tags if a properly formatted barcode is detected.
|
||||
|
||||
Defaults to false.
|
||||
|
||||
#### [`PAPERLESS_CONSUMER_STORE_BARCODE_VALUES=<bool>`](#PAPERLESS_CONSUMER_STORE_BARCODE_VALUES) {#PAPERLESS_CONSUMER_STORE_BARCODE_VALUES}
|
||||
|
||||
: Stores the content of every barcode found during consumption, see
|
||||
[Barcode Contents](advanced_usage.md#barcode-contents).
|
||||
|
||||
Defaults to false.
|
||||
|
||||
## Audit Trail
|
||||
|
||||
#### [`PAPERLESS_AUDIT_LOG_ENABLED=<bool>`](#PAPERLESS_AUDIT_LOG_ENABLED) {#PAPERLESS_AUDIT_LOG_ENABLED}
|
||||
|
||||
+1
-3
@@ -76,9 +76,7 @@ is not supported by any of the available parsers.
|
||||
|
||||
**A:** Not by default. As of v3, a file whose contents match an existing document is still
|
||||
consumed, and the duplicate is flagged in the UI — open the document and check the
|
||||
**Duplicates** tab to review documents that share the same content, or filter the document
|
||||
list by **Duplicates** to find all of them (see
|
||||
[Duplicate documents](usage.md#duplicate-documents)). If you prefer the old
|
||||
**Duplicates** tab to review documents that share the same content. If you prefer the old
|
||||
behavior of rejecting duplicates during consumption, set
|
||||
[`PAPERLESS_CONSUMER_DELETE_DUPLICATES`](configuration.md#PAPERLESS_CONSUMER_DELETE_DUPLICATES)
|
||||
to `true`.
|
||||
|
||||
+3
-2
@@ -13,8 +13,9 @@ physical documents into a searchable online archive so you can keep, well, _less
|
||||
[Demo](https://demo.paperless-ngx.com){ .md-button .md-button--secondary target=\_blank }
|
||||
|
||||
<div style="display: flex; justify-content: end; margin-top: -1.5rem;">
|
||||
<a href="https://fyrastack.com" target="_blank" aria-label="Demo hosting provided by Fyra Stack">
|
||||
<img src="assets/sponsors/fyra-stack.svg" alt="" class="no-lightbox" width="28px" style="vertical-align: middle;"> Fyra Stack
|
||||
<a href="https://m.do.co/c/8d70b916d462" target="_blank">
|
||||
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/PoweredByDO/DO_Powered_by_Badge_white.svg#only-dark" class="no-lightbox" width="150px">
|
||||
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/PoweredByDO/DO_Powered_by_Badge_black.svg#only-light" class="no-lightbox" width="150px">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -272,65 +272,6 @@ This error can occur in installations which have upgraded from a version of Pape
|
||||
$ python3 manage.py convert_mariadb_uuid
|
||||
```
|
||||
|
||||
## MariaDB/MySQL error "Illegal mix of collations"
|
||||
|
||||
Consumption or other operations fail with an error like:
|
||||
|
||||
```
|
||||
(1267, "Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and
|
||||
(utf8mb4_unicode_ci,IMPLICIT) for operation '='")
|
||||
```
|
||||
|
||||
This happens when the tables in your database do not all use the same
|
||||
collation. It is most often seen on databases that existed before a
|
||||
MariaDB/MySQL upgrade: older tables keep their original collation, while
|
||||
tables created afterwards use the new server default.
|
||||
|
||||
To work around it, set the collation your existing tables use (the one in the error
|
||||
that is not `utf8mb4_unicode_ci`) with
|
||||
[`PAPERLESS_DB_OPTIONS`](configuration.md#PAPERLESS_DB_OPTIONS):
|
||||
|
||||
```bash
|
||||
PAPERLESS_DB_OPTIONS="collation=utf8mb4_general_ci"
|
||||
```
|
||||
|
||||
To fix it permanently, back up your database, then convert the database and
|
||||
each table to a single collation and remove the override:
|
||||
|
||||
```sql
|
||||
ALTER DATABASE paperless CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
ALTER TABLE <table_name> CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
## PostgreSQL warns about a "collation version mismatch"
|
||||
|
||||
The PostgreSQL log shows a warning like:
|
||||
|
||||
```
|
||||
WARNING: database "paperless" has a collation version mismatch
|
||||
DETAIL: The database was created using collation version 2.36, but the operating system provides version 2.41.
|
||||
HINT: Rebuild all objects in this database that use the default collation and run ALTER DATABASE paperless REFRESH COLLATION VERSION, or build PostgreSQL with the right library version.
|
||||
```
|
||||
|
||||
This comes from PostgreSQL, not Paperless-ngx. The `glibc` version that PostgreSQL
|
||||
runs against changed, and the existing database was created with an older one. With
|
||||
Docker, `glibc` comes from the PostgreSQL image's Debian base, not the host, so this
|
||||
commonly happens when a new image is pulled after its base Debian release changed.
|
||||
If PostgreSQL is installed directly on a host, it uses the host's `glibc` instead.
|
||||
|
||||
The warning is not an error and Paperless-ngx keeps working, but the database's text
|
||||
indexes may be built with outdated sorting rules. To resolve it, back up your
|
||||
database, then connect to it (for example with `psql -U paperless -d paperless`
|
||||
inside the database container) and run:
|
||||
|
||||
```sql
|
||||
REINDEX DATABASE paperless;
|
||||
ALTER DATABASE paperless REFRESH COLLATION VERSION;
|
||||
```
|
||||
|
||||
To avoid this in the future, pin your PostgreSQL image to a specific Debian release,
|
||||
for example `postgres:18-trixie`, rather than `postgres:18`.
|
||||
|
||||
## Platform-Specific Deployment Troubleshooting
|
||||
|
||||
A user-maintained wiki page is available to help troubleshoot issues that may arise when trying to deploy Paperless-ngx on specific platforms, for example SELinux. Please see [the wiki](https://github.com/paperless-ngx/paperless-ngx/wiki/Platform%E2%80%90Specific-Troubleshooting).
|
||||
+8
-21
@@ -299,18 +299,19 @@ for details.
|
||||
### Duplicate documents
|
||||
|
||||
By default, Paperless-ngx **does not reject duplicates**. If you consume a file whose
|
||||
contents match an existing document (same original or archive checksum), the new copy is
|
||||
still consumed and a warning is logged.
|
||||
contents exactly match an existing document (same checksum), the new copy is still
|
||||
consumed and a warning is logged. The task entry for the upload also flags that a
|
||||
duplicate was detected and links to the existing document(s).
|
||||
|
||||
When a document has duplicates, a **Duplicates** tab appears on its detail page, listing
|
||||
the other documents you can view that share the same content (including any in the trash).
|
||||
To find all documents with duplicates, choose **Duplicates** in the document list's text
|
||||
filter dropdown, or use `has_duplicates=true` in the REST API.
|
||||
To review duplicates, open a document and switch to the **Duplicates** tab on the
|
||||
document detail page. It lists other documents that share the same content, including any
|
||||
that are in the trash (shown with a badge), and links to each so you can decide which to
|
||||
keep.
|
||||
|
||||
If you would rather reject duplicates at consumption time (the pre-v3 behavior), set
|
||||
[`PAPERLESS_CONSUMER_DELETE_DUPLICATES`](configuration.md#PAPERLESS_CONSUMER_DELETE_DUPLICATES)
|
||||
to `true`. The duplicate file is then deleted instead of consumed, and the task fails with
|
||||
a "Document already exists" message linking to the existing document.
|
||||
a "document already exists" message.
|
||||
|
||||
## Document Suggestions
|
||||
|
||||
@@ -1060,20 +1061,6 @@ notes.user:alice notes.note:insurance
|
||||
|
||||
The bare `notes:` prefix is shorthand for `notes.note:`.
|
||||
|
||||
#### Searching barcodes
|
||||
|
||||
If [barcode contents are stored](advanced_usage.md#barcode-contents), they can be searched by
|
||||
content or type, but only with a field name:
|
||||
|
||||
```
|
||||
barcodes.value:DE89370400440532013000
|
||||
barcodes.format:qrcode
|
||||
barcodes:wifi barcodes:guest
|
||||
```
|
||||
|
||||
`barcodes:` is shorthand for `barcodes.value:`. Separators are stripped, so each part of e.g.
|
||||
`WIFI:S:Guest;P:secret;;` can be searched on its own.
|
||||
|
||||
All of these can be combined. Syntax not described here may not work as expected, and an unknown field name is searched as ordinary text.
|
||||
|
||||
!!! note
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "paperless-ngx"
|
||||
version = "3.3.0"
|
||||
version = "3.2.1"
|
||||
description = """\
|
||||
A community-supported supercharged document management system: scan, index and archive all your physical documents\
|
||||
"""
|
||||
@@ -33,7 +33,7 @@ dependencies = [
|
||||
"django-compression-middleware~=0.5.0",
|
||||
"django-cors-headers~=4.9.0",
|
||||
"django-extensions~=4.1",
|
||||
"django-filter>=25.1,<27",
|
||||
"django-filter~=25.1",
|
||||
"django-guardian>=3.3.3,<3.6",
|
||||
"django-multiselectfield~=1.0.1",
|
||||
"django-rich~=2.2.0",
|
||||
@@ -90,7 +90,7 @@ postgres = [
|
||||
"psycopg[c,pool]==3.3.4",
|
||||
# Direct dependency for proper resolution of the pre-built wheels
|
||||
"psycopg-c==3.3.4",
|
||||
"psycopg-pool==3.3.3",
|
||||
"psycopg-pool==3.3.2",
|
||||
]
|
||||
webserver = [
|
||||
"granian[uvloop]>=2.7,<2.9",
|
||||
|
||||
+113
-150
@@ -698,7 +698,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">463,464</context>
|
||||
<context context-type="linenumber">457,458</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/custom-fields-bulk-edit-dialog/custom-fields-bulk-edit-dialog.component.html</context>
|
||||
@@ -870,7 +870,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">482</context>
|
||||
<context context-type="linenumber">476</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
||||
@@ -1373,7 +1373,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1907</context>
|
||||
<context context-type="linenumber">1901</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1577733187050997705" datatype="html">
|
||||
@@ -1451,7 +1451,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">408,409</context>
|
||||
<context context-type="linenumber">402,403</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||
@@ -1700,7 +1700,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">179</context>
|
||||
<context context-type="linenumber">177</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2691296884221415710" datatype="html">
|
||||
@@ -1715,7 +1715,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">184</context>
|
||||
<context context-type="linenumber">182</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||
@@ -1750,7 +1750,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">188</context>
|
||||
<context context-type="linenumber">186</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||
@@ -1785,7 +1785,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">192</context>
|
||||
<context context-type="linenumber">190</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
|
||||
@@ -2478,7 +2478,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">713</context>
|
||||
<context context-type="linenumber">711</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-version-dropdown/document-version-dropdown.component.html</context>
|
||||
@@ -3392,11 +3392,11 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1521</context>
|
||||
<context context-type="linenumber">1515</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1908</context>
|
||||
<context context-type="linenumber">1902</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||
@@ -4012,7 +4012,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1474</context>
|
||||
<context context-type="linenumber">1468</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||
@@ -4156,7 +4156,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1961</context>
|
||||
<context context-type="linenumber">1955</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6661109599266152398" datatype="html">
|
||||
@@ -4167,7 +4167,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1962</context>
|
||||
<context context-type="linenumber">1956</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5162686434580248853" datatype="html">
|
||||
@@ -4178,7 +4178,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1963</context>
|
||||
<context context-type="linenumber">1957</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6665634854532231106" datatype="html">
|
||||
@@ -5430,7 +5430,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">374,375</context>
|
||||
<context context-type="linenumber">368,369</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8057014866157903311" datatype="html">
|
||||
@@ -6311,7 +6311,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1478</context>
|
||||
<context context-type="linenumber">1472</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||
@@ -6344,7 +6344,7 @@
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">177</context>
|
||||
<context context-type="linenumber">175</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
|
||||
@@ -7176,10 +7176,6 @@
|
||||
<context context-type="sourcefile">src/app/components/common/system-status-dialog/system-status-dialog.component.html</context>
|
||||
<context context-type="linenumber">56,57</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-barcodes/document-barcodes.component.html</context>
|
||||
<context context-type="linenumber">5,6</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1230154438678955604" datatype="html">
|
||||
<source>Change</source>
|
||||
@@ -7752,8 +7748,8 @@
|
||||
<context context-type="linenumber">120</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5377184518735933155" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =1 {1 suggestion available below} other {<x id="INTERPOLATION"/> suggestions available below}}</source>
|
||||
<trans-unit id="5700628356844396417" datatype="html">
|
||||
<source>{VAR_PLURAL, plural, =1 {1 existing value suggested below} other {<x id="INTERPOLATION"/> existing values suggested below}}</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/common/suggestions-dropdown/suggestions-dropdown.component.html</context>
|
||||
<context context-type="linenumber">54</context>
|
||||
@@ -8337,10 +8333,6 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="1407560924967345762" datatype="html">
|
||||
<source>Page</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-barcodes/document-barcodes.component.html</context>
|
||||
<context context-type="linenumber">4,5</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">5,6</context>
|
||||
@@ -8354,28 +8346,6 @@
|
||||
<context context-type="linenumber">34</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6205355627445317276" datatype="html">
|
||||
<source>Content</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-barcodes/document-barcodes.component.html</context>
|
||||
<context context-type="linenumber">6,7</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">300,301</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3846359579066496296" datatype="html">
|
||||
<source>Copy content</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-barcodes/document-barcodes.component.html</context>
|
||||
<context context-type="linenumber">32,33</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-barcodes/document-barcodes.component.html</context>
|
||||
<context context-type="linenumber">40,41</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2266163016683537825" datatype="html">
|
||||
<source>of <x id="INTERPOLATION" equiv-text="{{previewNumPages()}}"/></source>
|
||||
<context-group purpose="location">
|
||||
@@ -8507,32 +8477,39 @@
|
||||
<source>Details</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">174,175</context>
|
||||
<context context-type="linenumber">172,173</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5114742157723900905" datatype="html">
|
||||
<source>Date created</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">181</context>
|
||||
<context context-type="linenumber">179</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5607669932062416162" datatype="html">
|
||||
<source>Default</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">193</context>
|
||||
<context context-type="linenumber">191</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/manage/saved-views/saved-views.component.html</context>
|
||||
<context context-type="linenumber">71</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6205355627445317276" datatype="html">
|
||||
<source>Content</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">298,299</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="218403386307979629" datatype="html">
|
||||
<source>Metadata</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">309,310</context>
|
||||
<context context-type="linenumber">307,308</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/metadata-collapse/metadata-collapse.component.ts</context>
|
||||
@@ -8543,235 +8520,228 @@
|
||||
<source>Date modified</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">316,317</context>
|
||||
<context context-type="linenumber">314,315</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6392918669949841614" datatype="html">
|
||||
<source>Date added</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">320,321</context>
|
||||
<context context-type="linenumber">318,319</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="146828917013192897" datatype="html">
|
||||
<source>Media filename</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">324,325</context>
|
||||
<context context-type="linenumber">322,323</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4500855521601039868" datatype="html">
|
||||
<source>Original filename</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">328,329</context>
|
||||
<context context-type="linenumber">326,327</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2659735245739197634" datatype="html">
|
||||
<source>Original SHA256 checksum</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">332,333</context>
|
||||
<context context-type="linenumber">330,331</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5888243105821763422" datatype="html">
|
||||
<source>Original file size</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">336,337</context>
|
||||
<context context-type="linenumber">334,335</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2696647325713149563" datatype="html">
|
||||
<source>Original mime type</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">340,341</context>
|
||||
<context context-type="linenumber">338,339</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6714358112223607756" datatype="html">
|
||||
<source>Archive SHA256 checksum</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">345,346</context>
|
||||
<context context-type="linenumber">343,344</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6033581412811562084" datatype="html">
|
||||
<source>Archive file size</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">351,352</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8459338343197260257" datatype="html">
|
||||
<source>Barcodes</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">360,361</context>
|
||||
<context context-type="linenumber">349,350</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6992781481378431874" datatype="html">
|
||||
<source>Original document metadata</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">364</context>
|
||||
<context context-type="linenumber">358</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2846565152091361585" datatype="html">
|
||||
<source>Archived document metadata</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">367</context>
|
||||
<context context-type="linenumber">361</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7206723502037428235" datatype="html">
|
||||
<source>Notes <x id="START_BLOCK_IF" equiv-text="@if (document()?.notes.length) {"/><x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="badge text-bg-secondary ms-1">"/><x id="INTERPOLATION" equiv-text="{{document().notes.length}}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/><x id="CLOSE_BLOCK_IF" equiv-text="}"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">386,389</context>
|
||||
<context context-type="linenumber">380,383</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="186236568870281953" datatype="html">
|
||||
<source>History</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">397,398</context>
|
||||
<context context-type="linenumber">391,392</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8236092845697214347" datatype="html">
|
||||
<source> Duplicates <x id="START_TAG_SPAN" ctype="x-span" equiv-text="<span class="badge text-bg-secondary ms-1">"/><x id="INTERPOLATION" equiv-text="{{ document().duplicate_documents.length }}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="</span>"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">420,423</context>
|
||||
<context context-type="linenumber">414,417</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6449374629822973702" datatype="html">
|
||||
<source>Duplicate documents detected:</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">425,426</context>
|
||||
<context context-type="linenumber">419,420</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="14058600336670816" datatype="html">
|
||||
<source>In trash</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">436,437</context>
|
||||
<context context-type="linenumber">430,431</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5129524307369213584" datatype="html">
|
||||
<source>Save & next</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">465</context>
|
||||
<context context-type="linenumber">459</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4910102545766233758" datatype="html">
|
||||
<source>Save & close</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">467</context>
|
||||
<context context-type="linenumber">461</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3823219296477075982" datatype="html">
|
||||
<source>Discard</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">469,470</context>
|
||||
<context context-type="linenumber">463,464</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1309556917227148591" datatype="html">
|
||||
<source>Document loading...</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">477</context>
|
||||
<context context-type="linenumber">471</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8191371354890763172" datatype="html">
|
||||
<source>Enter Password</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.html</context>
|
||||
<context context-type="linenumber">531</context>
|
||||
<context context-type="linenumber">525</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5758784066858623886" datatype="html">
|
||||
<source>Error retrieving metadata</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">463</context>
|
||||
<context context-type="linenumber">461</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2218903673684131427" datatype="html">
|
||||
<source>An error occurred loading content: <x id="PH" equiv-text="err.message ?? err.toString()"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">566,568</context>
|
||||
<context context-type="linenumber">564,566</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1047,1049</context>
|
||||
<context context-type="linenumber">1045,1047</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6357361810318120957" datatype="html">
|
||||
<source>Document was updated</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">708</context>
|
||||
<context context-type="linenumber">706</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="5154064822428631306" datatype="html">
|
||||
<source>Document was updated at <x id="PH" equiv-text="formattedModified"/>.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">709</context>
|
||||
<context context-type="linenumber">707</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8462497568316256794" datatype="html">
|
||||
<source>Reload to discard your local unsaved edits and load the latest remote version.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">710</context>
|
||||
<context context-type="linenumber">708</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7967484035994732534" datatype="html">
|
||||
<source>Reload</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">712</context>
|
||||
<context context-type="linenumber">710</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2907037627372942104" datatype="html">
|
||||
<source>Document reloaded with latest changes.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">768</context>
|
||||
<context context-type="linenumber">766</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6435639868943916539" datatype="html">
|
||||
<source>Document reloaded.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">779</context>
|
||||
<context context-type="linenumber">777</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6142395741265832184" datatype="html">
|
||||
<source>Next document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">881</context>
|
||||
<context context-type="linenumber">879</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="651985345816518480" datatype="html">
|
||||
<source>Previous document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">891</context>
|
||||
<context context-type="linenumber">889</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2885986061416655600" datatype="html">
|
||||
<source>Close document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">899</context>
|
||||
<context context-type="linenumber">897</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/services/open-documents.service.ts</context>
|
||||
@@ -8782,28 +8752,28 @@
|
||||
<source>Save document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">906</context>
|
||||
<context context-type="linenumber">904</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1784543155727940353" datatype="html">
|
||||
<source>Save and close / next</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">915</context>
|
||||
<context context-type="linenumber">913</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7427704425579737895" datatype="html">
|
||||
<source>Error retrieving version content</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1029</context>
|
||||
<context context-type="linenumber">1027</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="159901853873315050" datatype="html">
|
||||
<source>Unsaved Changes</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1073</context>
|
||||
<context context-type="linenumber">1071</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/guards/dirty-form.guard.ts</context>
|
||||
@@ -8826,74 +8796,74 @@
|
||||
<source>You have unsaved changes to the content of this version.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1074</context>
|
||||
<context context-type="linenumber">1072</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="85184271222513014" datatype="html">
|
||||
<source>Switching versions will discard them.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1075</context>
|
||||
<context context-type="linenumber">1073</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2565707334844767610" datatype="html">
|
||||
<source>Discard and switch</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1077</context>
|
||||
<context context-type="linenumber">1075</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2109314380040637387" datatype="html">
|
||||
<source>Save and switch</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1079</context>
|
||||
<context context-type="linenumber">1077</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3456881259945295697" datatype="html">
|
||||
<source>Error retrieving suggestions.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1122</context>
|
||||
<context context-type="linenumber">1120</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2194092841814123758" datatype="html">
|
||||
<source>Document "<x id="PH" equiv-text="newValues.title"/>" saved successfully.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1353</context>
|
||||
<context context-type="linenumber">1347</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1381</context>
|
||||
<context context-type="linenumber">1375</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6626387786259219838" datatype="html">
|
||||
<source>Error saving document "<x id="PH" equiv-text="this.document().title"/>"</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1387</context>
|
||||
<context context-type="linenumber">1381</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="448882439049417053" datatype="html">
|
||||
<source>Error saving document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1442</context>
|
||||
<context context-type="linenumber">1436</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8410796510716511826" datatype="html">
|
||||
<source>Do you really want to move the document "<x id="PH" equiv-text="this.document().title"/>" to the trash?</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1475</context>
|
||||
<context context-type="linenumber">1469</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="282586936710748252" datatype="html">
|
||||
<source>Documents can be restored prior to permanent deletion.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1476</context>
|
||||
<context context-type="linenumber">1470</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||
@@ -8904,14 +8874,14 @@
|
||||
<source>Error deleting document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1497</context>
|
||||
<context context-type="linenumber">1491</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="619486176823357521" datatype="html">
|
||||
<source>Reprocess confirm</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1517</context>
|
||||
<context context-type="linenumber">1511</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.ts</context>
|
||||
@@ -8922,102 +8892,102 @@
|
||||
<source>This operation will permanently recreate the archive file for this document.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1518</context>
|
||||
<context context-type="linenumber">1512</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="302054111564709516" datatype="html">
|
||||
<source>The archive file will be re-generated with the current settings.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1519</context>
|
||||
<context context-type="linenumber">1513</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4700389117298802932" datatype="html">
|
||||
<source>Reprocess operation for "<x id="PH" equiv-text="this.document().title"/>" will begin in the background.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1532</context>
|
||||
<context context-type="linenumber">1526</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4409560272830824468" datatype="html">
|
||||
<source>Error executing operation</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1543</context>
|
||||
<context context-type="linenumber">1537</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6030453331794586802" datatype="html">
|
||||
<source>Error downloading document</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1607</context>
|
||||
<context context-type="linenumber">1601</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4458954481601077369" datatype="html">
|
||||
<source>Page Fit</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1685</context>
|
||||
<context context-type="linenumber">1679</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4663705961777238777" datatype="html">
|
||||
<source>PDF edit operation for "<x id="PH" equiv-text="this.document().title"/>" will begin in the background.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1928</context>
|
||||
<context context-type="linenumber">1922</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="9043972994040261999" datatype="html">
|
||||
<source>Error executing PDF edit operation</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1940</context>
|
||||
<context context-type="linenumber">1934</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6172690334763056188" datatype="html">
|
||||
<source>Please enter the current password before attempting to remove it.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1951</context>
|
||||
<context context-type="linenumber">1945</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="968660764814228922" datatype="html">
|
||||
<source>Password removal operation for "<x id="PH" equiv-text="this.document().title"/>" will begin in the background.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1985</context>
|
||||
<context context-type="linenumber">1979</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2282118435712883014" datatype="html">
|
||||
<source>Error executing password removal operation</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">1999</context>
|
||||
<context context-type="linenumber">1993</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3740891324955700797" datatype="html">
|
||||
<source>Print failed.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">2049</context>
|
||||
<context context-type="linenumber">2043</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6457245677384603573" datatype="html">
|
||||
<source>Error loading document for printing.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">2058</context>
|
||||
<context context-type="linenumber">2052</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6085793215710522488" datatype="html">
|
||||
<source>An error occurred loading tiff: <x id="PH" equiv-text="err.toString()"/></source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">2141</context>
|
||||
<context context-type="linenumber">2135</context>
|
||||
</context-group>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/components/document-detail/document-detail.component.ts</context>
|
||||
<context context-type="linenumber">2147</context>
|
||||
<context context-type="linenumber">2141</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4958946940233632319" datatype="html">
|
||||
@@ -12083,130 +12053,123 @@
|
||||
<context context-type="linenumber">328</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="906679600349814230" datatype="html">
|
||||
<source>Store Barcode Contents</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">335</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7011909364081812031" datatype="html">
|
||||
<source>AI Enabled</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">342</context>
|
||||
<context context-type="linenumber">335</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8028880048909383956" datatype="html">
|
||||
<source>Consider privacy implications when enabling AI features, especially if using a remote model.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">346</context>
|
||||
<context context-type="linenumber">339</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="8131374115579345652" datatype="html">
|
||||
<source>LLM Embedding Backend</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">350</context>
|
||||
<context context-type="linenumber">343</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6647708571891295756" datatype="html">
|
||||
<source>LLM Embedding Model</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">358</context>
|
||||
<context context-type="linenumber">351</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="861068592166833023" datatype="html">
|
||||
<source>LLM Embedding API Key</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">365</context>
|
||||
<context context-type="linenumber">358</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="2929108042259892948" datatype="html">
|
||||
<source>Used for embeddings when set, otherwise LLM API key is used.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">367</context>
|
||||
<context context-type="linenumber">360</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3554114880473286122" datatype="html">
|
||||
<source>LLM Embedding Endpoint</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">373</context>
|
||||
<context context-type="linenumber">366</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1044242175651289991" datatype="html">
|
||||
<source>LLM Embedding Chunk Size</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">380</context>
|
||||
<context context-type="linenumber">373</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7218245223139363113" datatype="html">
|
||||
<source>LLM Context Size</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">387</context>
|
||||
<context context-type="linenumber">380</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4234495692726214397" datatype="html">
|
||||
<source>LLM Backend</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">394</context>
|
||||
<context context-type="linenumber">387</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="7935234833834000002" datatype="html">
|
||||
<source>LLM Model</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">402</context>
|
||||
<context context-type="linenumber">395</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1980550530387803165" datatype="html">
|
||||
<source>LLM API Key</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">409</context>
|
||||
<context context-type="linenumber">402</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6126617860376156501" datatype="html">
|
||||
<source>LLM Endpoint</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">416</context>
|
||||
<context context-type="linenumber">409</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="6572826277249350975" datatype="html">
|
||||
<source>LLM Output Language</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">423</context>
|
||||
<context context-type="linenumber">416</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="3284403507172415792" datatype="html">
|
||||
<source>Language to use for generated AI suggestions. When unset, AI suggestions use the user's display language if explicitly set.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">427</context>
|
||||
<context context-type="linenumber">420</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="4493921125434706859" datatype="html">
|
||||
<source>LLM Request Timeout</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">431</context>
|
||||
<context context-type="linenumber">424</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="483994032066441287" datatype="html">
|
||||
<source>Timeout in seconds for LLM requests.</source>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/data/paperless-config.ts</context>
|
||||
<context context-type="linenumber">435</context>
|
||||
<context context-type="linenumber">428</context>
|
||||
</context-group>
|
||||
</trans-unit>
|
||||
<trans-unit id="1055686627716339120" datatype="html">
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "paperless-ngx-ui",
|
||||
"version": "3.3.0",
|
||||
"version": "3.2.1",
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"ng": "ng",
|
||||
|
||||
+3
-3
@@ -26,7 +26,7 @@
|
||||
|
||||
<div ngbDropdownMenu aria-labelledby="suggestionsDropdown" class="shadow suggestions-dropdown">
|
||||
<div class="list-group list-group-flush small pb-0">
|
||||
@if (novelSuggestions === 0 && fieldSuggestions === 0) {
|
||||
@if (novelSuggestions === 0 && reusableSuggestions === 0) {
|
||||
<div class="list-group-item text-muted fst-italic">
|
||||
<small class="text-muted small fst-italic" i18n>No novel suggestions</small>
|
||||
</div>
|
||||
@@ -49,9 +49,9 @@
|
||||
<button type="button" class="list-group-item list-group-item-action bg-light" (click)="addCorrespondent.emit(correspondent)">{{ correspondent }}</button>
|
||||
}
|
||||
}
|
||||
@if (fieldSuggestions > 0) {
|
||||
@if (reusableSuggestions > 0) {
|
||||
<div class="list-group-item text-muted fst-italic">
|
||||
<small class="text-muted small fst-italic" i18n>{fieldSuggestions, plural, =1 {1 suggestion available below} other {{{fieldSuggestions}} suggestions available below}}</small>
|
||||
<small class="text-muted small fst-italic" i18n>{reusableSuggestions, plural, =1 {1 existing value suggested below} other {{{reusableSuggestions}} existing values suggested below}}</small>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
+4
-62
@@ -84,7 +84,7 @@ describe('SuggestionsDropdownComponent', () => {
|
||||
fixture.detectChanges()
|
||||
|
||||
expect(fixture.nativeElement.textContent).toContain(
|
||||
'2 suggestions available below'
|
||||
'2 existing values suggested below'
|
||||
)
|
||||
expect(fixture.nativeElement.textContent).not.toContain(
|
||||
'No novel suggestions'
|
||||
@@ -108,7 +108,7 @@ describe('SuggestionsDropdownComponent', () => {
|
||||
expect(component.totalSuggestions).toBe(4)
|
||||
expect(fixture.nativeElement.textContent).toContain('Arbitration')
|
||||
expect(fixture.nativeElement.textContent).toContain(
|
||||
'2 suggestions available below'
|
||||
'2 existing values suggested below'
|
||||
)
|
||||
})
|
||||
|
||||
@@ -125,46 +125,10 @@ describe('SuggestionsDropdownComponent', () => {
|
||||
})
|
||||
|
||||
expect(component.novelSuggestions).toBe(0)
|
||||
expect(component.totalSuggestions).toBe(6)
|
||||
expect(component.totalSuggestions).toBe(5)
|
||||
|
||||
fixture.componentRef.setInput('appliedStoragePath', 7)
|
||||
expect(component.totalSuggestions).toBe(5)
|
||||
})
|
||||
|
||||
it('should count title and dates as field suggestions without calling them existing values', () => {
|
||||
fixture.componentRef.setInput('aiEnabled', true)
|
||||
fixture.componentRef.setInput('fetchedSources', [SuggestionSource.ML])
|
||||
fixture.componentRef.setInput('suggestions', {
|
||||
title: 'Suggested title',
|
||||
dates: ['2026-01-04', '2026-02-01', '2026-03-01'],
|
||||
correspondents: [1, 2, 3, 4],
|
||||
document_types: [1, 2, 3, 4],
|
||||
tags: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
})
|
||||
fixture.detectChanges()
|
||||
component.clickSuggest()
|
||||
fixture.detectChanges()
|
||||
|
||||
expect(component.reusableSuggestions).toBe(16)
|
||||
expect(component.fieldSuggestions).toBe(20)
|
||||
expect(component.totalSuggestions).toBe(20)
|
||||
expect(fixture.nativeElement.textContent).toContain(
|
||||
'20 suggestions available below'
|
||||
)
|
||||
expect(fixture.nativeElement.textContent).not.toContain('existing value')
|
||||
})
|
||||
|
||||
it('should not count title or date suggestions matching the current values', () => {
|
||||
fixture.componentRef.setInput('suggestions', {
|
||||
title: 'Current title',
|
||||
dates: ['2026-01-04', '2026-02-01'],
|
||||
})
|
||||
expect(component.fieldSuggestions).toBe(3)
|
||||
|
||||
fixture.componentRef.setInput('appliedTitle', 'Current title')
|
||||
fixture.componentRef.setInput('appliedCreated', '2026-01-04')
|
||||
expect(component.fieldSuggestions).toBe(1)
|
||||
expect(component.totalSuggestions).toBe(1)
|
||||
expect(component.totalSuggestions).toBe(4)
|
||||
})
|
||||
|
||||
it('should show when a completed request returned no suggestions', () => {
|
||||
@@ -181,28 +145,6 @@ describe('SuggestionsDropdownComponent', () => {
|
||||
expect(fixture.nativeElement.textContent).toContain('No suggestions')
|
||||
})
|
||||
|
||||
it('should wait for all pending responses before showing the empty state', () => {
|
||||
fixture.componentRef.setInput('aiEnabled', true)
|
||||
fixture.componentRef.setInput('source', SuggestionSource.Both)
|
||||
fixture.componentRef.setInput('fetchedSources', [SuggestionSource.ML])
|
||||
fixture.componentRef.setInput('suggestions', { tags: [] })
|
||||
fixture.componentRef.setInput('loading', true)
|
||||
fixture.detectChanges()
|
||||
|
||||
expect(component.noSuggestions).toBeFalsy()
|
||||
expect(fixture.nativeElement.textContent).not.toContain('No suggestions')
|
||||
expect(
|
||||
fixture.nativeElement.querySelector('[role="status"]')
|
||||
).not.toBeNull()
|
||||
|
||||
fixture.componentRef.setInput('loading', false)
|
||||
fixture.detectChanges()
|
||||
|
||||
expect(component.noSuggestions).toBeTruthy()
|
||||
expect(fixture.nativeElement.textContent).toContain('No suggestions')
|
||||
expect(fixture.nativeElement.querySelector('[role="status"]')).toBeNull()
|
||||
})
|
||||
|
||||
it('should not show the empty state before a request or with suggestions', () => {
|
||||
expect(component.noSuggestions).toBeFalsy()
|
||||
|
||||
|
||||
+1
-25
@@ -34,8 +34,6 @@ export class SuggestionsDropdownComponent {
|
||||
readonly appliedCorrespondent = input<number>(null)
|
||||
readonly appliedDocumentType = input<number>(null)
|
||||
readonly appliedStoragePath = input<number>(null)
|
||||
readonly appliedTitle = input<string>(null)
|
||||
readonly appliedCreated = input<string>(null)
|
||||
|
||||
@Output()
|
||||
getSuggestions: EventEmitter<SuggestionSource> = new EventEmitter()
|
||||
@@ -130,28 +128,7 @@ export class SuggestionsDropdownComponent {
|
||||
}
|
||||
|
||||
get totalSuggestions(): number {
|
||||
return this.novelSuggestions + this.fieldSuggestions
|
||||
}
|
||||
|
||||
get fieldSuggestions(): number {
|
||||
return (
|
||||
this.reusableSuggestions +
|
||||
this.unappliedTitleSuggestions +
|
||||
this.unappliedDateSuggestions
|
||||
)
|
||||
}
|
||||
|
||||
// hide a title or date suggestion equal to the current value
|
||||
private get unappliedTitleSuggestions(): number {
|
||||
const title = this.suggestions()?.title
|
||||
return title && title !== this.appliedTitle() ? 1 : 0
|
||||
}
|
||||
|
||||
private get unappliedDateSuggestions(): number {
|
||||
const created = this.appliedCreated()
|
||||
return (this.suggestions()?.dates ?? []).filter(
|
||||
(date) => !created || date !== created
|
||||
).length
|
||||
return this.novelSuggestions + this.reusableSuggestions
|
||||
}
|
||||
|
||||
private countUnapplied(suggested: number[], applied: number[]): number {
|
||||
@@ -162,7 +139,6 @@ export class SuggestionsDropdownComponent {
|
||||
get noSuggestions(): boolean {
|
||||
const suggestions = this.suggestions()
|
||||
return (
|
||||
!this.loading() &&
|
||||
suggestions != null &&
|
||||
!suggestions.title &&
|
||||
!suggestions.tags?.length &&
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
<table class="table table-borderless align-baseline">
|
||||
<thead>
|
||||
<tr>
|
||||
<th i18n>Page</th>
|
||||
<th i18n>Type</th>
|
||||
<th i18n>Content</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (barcode of barcodes(); track $index) {
|
||||
<tr>
|
||||
<td>{{ barcode.page }}</td>
|
||||
<td class="text-nowrap">{{ barcode.format }}</td>
|
||||
<td class="text-break">
|
||||
@if (isLink(barcode.value)) {
|
||||
<a
|
||||
[href]="barcode.value"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
>{{ barcode.value }}</a
|
||||
>
|
||||
} @else {
|
||||
{{ barcode.value }}
|
||||
}
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-outline-primary"
|
||||
(click)="copy($index)"
|
||||
title="Copy content"
|
||||
i18n-title
|
||||
>
|
||||
@if (copiedIndex() === $index) {
|
||||
<i-bs name="clipboard-check"></i-bs>
|
||||
} @else {
|
||||
<i-bs name="clipboard"></i-bs>
|
||||
}
|
||||
<span class="visually-hidden" i18n>Copy content</span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
import { Clipboard } from '@angular/cdk/clipboard'
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
|
||||
import { DocumentBarcodesComponent } from './document-barcodes.component'
|
||||
|
||||
const barcodes = [
|
||||
{ page: 1, value: 'ASN00123', format: 'Code128' },
|
||||
{ page: 2, value: 'https://example.com/invoice/4711', format: 'QRCode' },
|
||||
{ page: 2, value: 'javascript:alert(1)', format: 'QRCode' },
|
||||
]
|
||||
|
||||
describe('DocumentBarcodesComponent', () => {
|
||||
let component: DocumentBarcodesComponent
|
||||
let fixture: ComponentFixture<DocumentBarcodesComponent>
|
||||
let clipboard: Clipboard
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
DocumentBarcodesComponent,
|
||||
NgxBootstrapIconsModule.pick(allIcons),
|
||||
],
|
||||
}).compileComponents()
|
||||
|
||||
fixture = TestBed.createComponent(DocumentBarcodesComponent)
|
||||
component = fixture.componentInstance
|
||||
clipboard = TestBed.inject(Clipboard)
|
||||
fixture.componentRef.setInput('barcodes', barcodes)
|
||||
fixture.detectChanges()
|
||||
})
|
||||
|
||||
it('should display all barcodes', () => {
|
||||
const rows = fixture.nativeElement.querySelectorAll('tbody tr')
|
||||
expect(rows).toHaveLength(3)
|
||||
expect(rows[0].textContent).toContain('ASN00123')
|
||||
expect(rows[0].textContent).toContain('Code128')
|
||||
})
|
||||
|
||||
it('should only link http(s) values', () => {
|
||||
const links = fixture.nativeElement.querySelectorAll('tbody a')
|
||||
expect(links).toHaveLength(1)
|
||||
expect(links[0].getAttribute('href')).toEqual(
|
||||
'https://example.com/invoice/4711'
|
||||
)
|
||||
expect(links[0].getAttribute('target')).toEqual('_blank')
|
||||
})
|
||||
|
||||
it('should copy a value and show feedback', () => {
|
||||
jest.useFakeTimers()
|
||||
const copySpy = jest.spyOn(clipboard, 'copy').mockReturnValue(true)
|
||||
const buttons = fixture.nativeElement.querySelectorAll('tbody button')
|
||||
buttons[0].click()
|
||||
fixture.detectChanges()
|
||||
expect(copySpy).toHaveBeenCalledWith('ASN00123')
|
||||
expect(component.copiedIndex()).toEqual(0)
|
||||
expect(buttons[0].querySelector('i-bs').getAttribute('name')).toEqual(
|
||||
'clipboard-check'
|
||||
)
|
||||
jest.advanceTimersByTime(3000)
|
||||
fixture.detectChanges()
|
||||
expect(component.copiedIndex()).toBeNull()
|
||||
expect(buttons[0].querySelector('i-bs').getAttribute('name')).toEqual(
|
||||
'clipboard'
|
||||
)
|
||||
jest.useRealTimers()
|
||||
})
|
||||
|
||||
it('should not show feedback if copying failed', () => {
|
||||
jest.spyOn(clipboard, 'copy').mockReturnValue(false)
|
||||
component.copy(1)
|
||||
expect(component.copiedIndex()).toBeNull()
|
||||
})
|
||||
})
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
import { Clipboard } from '@angular/cdk/clipboard'
|
||||
import { Component, inject, input, OnDestroy, signal } from '@angular/core'
|
||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import { DocumentBarcode } from 'src/app/data/document-barcode'
|
||||
|
||||
@Component({
|
||||
selector: 'pngx-document-barcodes',
|
||||
templateUrl: './document-barcodes.component.html',
|
||||
imports: [NgxBootstrapIconsModule],
|
||||
})
|
||||
export class DocumentBarcodesComponent implements OnDestroy {
|
||||
private readonly clipboard = inject(Clipboard)
|
||||
|
||||
readonly barcodes = input<DocumentBarcode[]>([])
|
||||
|
||||
readonly copiedIndex = signal<number>(null)
|
||||
private copyTimeout: ReturnType<typeof setTimeout>
|
||||
|
||||
public isLink(value: string): boolean {
|
||||
try {
|
||||
const url = new URL(value.trim())
|
||||
return ['http:', 'https:'].includes(url.protocol) && !!url.host
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public copy(index: number) {
|
||||
if (!this.clipboard.copy(this.barcodes()[index].value)) return
|
||||
this.copiedIndex.set(index)
|
||||
clearTimeout(this.copyTimeout)
|
||||
this.copyTimeout = setTimeout(() => this.copiedIndex.set(null), 3000)
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
clearTimeout(this.copyTimeout)
|
||||
}
|
||||
}
|
||||
@@ -141,8 +141,6 @@
|
||||
[appliedCorrespondent]="documentForm.value.correspondent"
|
||||
[appliedDocumentType]="documentForm.value.document_type"
|
||||
[appliedStoragePath]="documentForm.value.storage_path"
|
||||
[appliedTitle]="documentForm.value.title"
|
||||
[appliedCreated]="documentForm.value.created"
|
||||
(getSuggestions)="getSuggestions($event)"
|
||||
(sourceChange)="suggestionSourceOverride.set($event)"
|
||||
(addTag)="createTag($event)"
|
||||
@@ -356,10 +354,6 @@
|
||||
</table>
|
||||
}
|
||||
|
||||
@if (metadata()?.barcodes?.length > 0) {
|
||||
<h6 i18n>Barcodes</h6>
|
||||
<pngx-document-barcodes [barcodes]="metadata().barcodes"></pngx-document-barcodes>
|
||||
}
|
||||
@if (metadata()?.original_metadata?.length > 0) {
|
||||
<pngx-metadata-collapse i18n-title title="Original document metadata" [metadata]="metadata()?.original_metadata"></pngx-metadata-collapse>
|
||||
}
|
||||
|
||||
@@ -662,45 +662,6 @@ describe('DocumentDetailComponent', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it.each([
|
||||
['tag', 'createTag', 'tags', 'suggested_tags'],
|
||||
[
|
||||
'document type',
|
||||
'createDocumentType',
|
||||
'document_type',
|
||||
'suggested_document_types',
|
||||
],
|
||||
[
|
||||
'correspondent',
|
||||
'createCorrespondent',
|
||||
'correspondent',
|
||||
'suggested_correspondents',
|
||||
],
|
||||
])(
|
||||
'should create a %s after ML-only suggestions',
|
||||
(_, method, field, suggestedField) => {
|
||||
initNormally()
|
||||
component.suggestions.set({ tags: [1] })
|
||||
let openModal: NgbModalRef
|
||||
modalService.activeInstances.subscribe((modal) => (openModal = modal[0]))
|
||||
component[method]('New value')
|
||||
openModal.componentInstance.succeeded.next({
|
||||
id: 12,
|
||||
name: 'New value',
|
||||
is_inbox_tag: false,
|
||||
color: '#ff0000',
|
||||
text_color: '#000000',
|
||||
})
|
||||
|
||||
if (field === 'tags') {
|
||||
expect(component.tagsInput.value).toContain(12)
|
||||
} else {
|
||||
expect(component.documentForm.get(field).value).toBe(12)
|
||||
}
|
||||
expect(component.suggestions()[suggestedField]).toEqual([])
|
||||
}
|
||||
)
|
||||
|
||||
it('should support creating storage path', () => {
|
||||
initNormally()
|
||||
let openModal: NgbModalRef
|
||||
|
||||
@@ -135,7 +135,6 @@ import { ShareLinksDialogComponent } from '../common/share-links-dialog/share-li
|
||||
import { SuggestionsDropdownComponent } from '../common/suggestions-dropdown/suggestions-dropdown.component'
|
||||
import { DocumentNotesComponent } from '../document-notes/document-notes.component'
|
||||
import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
|
||||
import { DocumentBarcodesComponent } from './document-barcodes/document-barcodes.component'
|
||||
import { DocumentHistoryComponent } from './document-history/document-history.component'
|
||||
import { DocumentVersionDropdownComponent } from './document-version-dropdown/document-version-dropdown.component'
|
||||
import { MetadataCollapseComponent } from './metadata-collapse/metadata-collapse.component'
|
||||
@@ -178,7 +177,6 @@ interface IncomingDocumentUpdate {
|
||||
DateComponent,
|
||||
DocumentLinkComponent,
|
||||
MetadataCollapseComponent,
|
||||
DocumentBarcodesComponent,
|
||||
PermissionsFormComponent,
|
||||
SelectComponent,
|
||||
TagsComponent,
|
||||
@@ -1154,7 +1152,7 @@ export class DocumentDetailComponent
|
||||
if (this.suggestions()) {
|
||||
this.suggestions.set({
|
||||
...this.suggestions(),
|
||||
suggested_tags: (this.suggestions().suggested_tags ?? []).filter(
|
||||
suggested_tags: this.suggestions().suggested_tags.filter(
|
||||
(tag) => tag !== newTag.name
|
||||
),
|
||||
})
|
||||
@@ -1193,12 +1191,10 @@ export class DocumentDetailComponent
|
||||
this.documentForm.get('document_type').setValue(newDocumentType.id)
|
||||
this.documentForm.get('document_type').markAsDirty()
|
||||
if (this.suggestions()) {
|
||||
this.suggestions.set({
|
||||
...this.suggestions(),
|
||||
suggested_document_types: (
|
||||
this.suggestions().suggested_document_types ?? []
|
||||
).filter((dt) => dt !== newName),
|
||||
})
|
||||
this.suggestions().suggested_document_types =
|
||||
this.suggestions().suggested_document_types.filter(
|
||||
(dt) => dt !== newName
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1225,12 +1221,10 @@ export class DocumentDetailComponent
|
||||
this.documentForm.get('correspondent').setValue(newCorrespondent.id)
|
||||
this.documentForm.get('correspondent').markAsDirty()
|
||||
if (this.suggestions()) {
|
||||
this.suggestions.set({
|
||||
...this.suggestions(),
|
||||
suggested_correspondents: (
|
||||
this.suggestions().suggested_correspondents ?? []
|
||||
).filter((c) => c !== newName),
|
||||
})
|
||||
this.suggestions().suggested_correspondents =
|
||||
this.suggestions().suggested_correspondents.filter(
|
||||
(c) => c !== newName
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
export interface DocumentBarcode {
|
||||
page: number
|
||||
|
||||
value: string
|
||||
|
||||
format: string
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import { DocumentBarcode } from './document-barcode'
|
||||
|
||||
export interface DocumentMetadata {
|
||||
original_checksum?: string
|
||||
|
||||
@@ -14,6 +12,4 @@ export interface DocumentMetadata {
|
||||
has_archive_version?: boolean
|
||||
|
||||
lang?: string
|
||||
|
||||
barcodes?: DocumentBarcode[]
|
||||
}
|
||||
@@ -330,13 +330,6 @@ export const PaperlessConfigOptions: ConfigOption[] = [
|
||||
config_key: 'PAPERLESS_CONSUMER_TAG_BARCODE_SPLIT',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'barcode_store_values',
|
||||
title: $localize`Store Barcode Contents`,
|
||||
type: ConfigOptionType.Boolean,
|
||||
config_key: 'PAPERLESS_CONSUMER_STORE_BARCODE_VALUES',
|
||||
category: ConfigCategory.Barcode,
|
||||
},
|
||||
{
|
||||
key: 'ai_enabled',
|
||||
title: $localize`AI Enabled`,
|
||||
@@ -465,7 +458,6 @@ export interface PaperlessConfig extends ObjectWithId {
|
||||
barcode_enable_tag: boolean
|
||||
barcode_tag_mapping: object
|
||||
barcode_tag_split: boolean
|
||||
barcode_store_values: boolean
|
||||
remote_ocr_engine: string
|
||||
remote_ocr_api_key: string
|
||||
remote_ocr_endpoint: string
|
||||
|
||||
@@ -8,7 +8,7 @@ export const environment = {
|
||||
apiVersion: '10', // match src/paperless/settings.py
|
||||
appTitle: DEFAULT_APP_TITLE,
|
||||
tag: 'prod',
|
||||
version: '3.3.0',
|
||||
version: '3.2.1',
|
||||
webSocketHost: window.location.host,
|
||||
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
|
||||
webSocketBaseUrl: base_url.pathname + 'ws/',
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -15,7 +15,7 @@
|
||||
"target": "ES2022",
|
||||
"module": "es2020",
|
||||
"lib": [
|
||||
"es2022",
|
||||
"es2020",
|
||||
"dom"
|
||||
],
|
||||
"useDefineForClassFields": false
|
||||
|
||||
+74
-126
@@ -18,7 +18,6 @@ from documents.converters import convert_from_tiff_to_pdf
|
||||
from documents.data_models import ConsumableDocument
|
||||
from documents.data_models import DocumentMetadataOverrides
|
||||
from documents.data_models import DocumentSource
|
||||
from documents.data_models import StoredBarcode
|
||||
from documents.models import Document
|
||||
from documents.models import PaperlessTask
|
||||
from documents.models import Tag
|
||||
@@ -48,7 +47,6 @@ class Barcode:
|
||||
page: int
|
||||
value: str
|
||||
settings: BarcodeConfig
|
||||
format: str = ""
|
||||
|
||||
@property
|
||||
def is_separator(self) -> bool:
|
||||
@@ -80,12 +78,6 @@ class Barcode:
|
||||
return True
|
||||
return False
|
||||
|
||||
def stored(self) -> StoredBarcode:
|
||||
"""
|
||||
The barcode as it is stored with a document, page 1-indexed
|
||||
"""
|
||||
return {"page": self.page + 1, "value": self.value, "format": self.format}
|
||||
|
||||
|
||||
class BarcodePlugin(ConsumeTaskPlugin):
|
||||
NAME: str = "BarcodePlugin"
|
||||
@@ -97,12 +89,16 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
||||
- ASN from barcode detection is enabled or
|
||||
- Barcode support is enabled and the mime type is supported
|
||||
"""
|
||||
if self.settings.barcode_enable_tiff_support:
|
||||
supported_mimes: set[str] = {"application/pdf", "image/tiff"}
|
||||
else:
|
||||
supported_mimes = {"application/pdf"}
|
||||
|
||||
return (
|
||||
self.settings.barcode_enable_asn
|
||||
or self.settings.barcodes_enabled
|
||||
or self.settings.barcode_enable_tag
|
||||
or self.settings.barcode_store_values
|
||||
) and self.input_doc.mime_type in scannable_mime_types(self.settings)
|
||||
) and self.input_doc.mime_type in supported_mimes
|
||||
|
||||
def get_settings(self) -> BarcodeConfig:
|
||||
"""
|
||||
@@ -248,10 +244,6 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
||||
if self.settings.barcode_enable_asn and (located_asn := self.asn) is not None:
|
||||
self._apply_detected_asn(located_asn)
|
||||
|
||||
# After splitting too, so each split document keeps its own barcodes
|
||||
if self.settings.barcode_store_values:
|
||||
self.metadata.barcodes = [x.stored() for x in self.barcodes] or None
|
||||
|
||||
def cleanup(self) -> None:
|
||||
self.temp_dir.cleanup()
|
||||
|
||||
@@ -270,6 +262,22 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
||||
)
|
||||
self._tiff_conversion_done = True
|
||||
|
||||
@staticmethod
|
||||
def read_barcodes_zxing(image: Image.Image) -> list[str]:
|
||||
barcodes = []
|
||||
|
||||
import zxingcpp
|
||||
|
||||
detected_barcodes = zxingcpp.read_barcodes(image)
|
||||
for barcode in detected_barcodes:
|
||||
if barcode.text:
|
||||
barcodes.append(barcode.text)
|
||||
logger.debug(
|
||||
f"Barcode of type {barcode.format} found: {barcode.text}",
|
||||
)
|
||||
|
||||
return barcodes
|
||||
|
||||
def detect(self) -> None:
|
||||
"""
|
||||
Scan all pages of the PDF as images, updating barcodes and the pages
|
||||
@@ -283,12 +291,60 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
||||
self.convert_from_tiff_to_pdf()
|
||||
|
||||
try:
|
||||
self.barcodes = scan_pdf(
|
||||
self.pdf_file,
|
||||
self.settings,
|
||||
Path(self.temp_dir.name),
|
||||
# Read number of pages from pdf
|
||||
with Pdf.open(self.pdf_file) as pdf:
|
||||
num_of_pages = len(pdf.pages)
|
||||
logger.debug(f"PDF has {num_of_pages} pages")
|
||||
|
||||
# Get limit from configuration
|
||||
barcode_max_pages: int = (
|
||||
num_of_pages
|
||||
if self.settings.barcode_max_pages == 0
|
||||
else self.settings.barcode_max_pages
|
||||
)
|
||||
|
||||
if barcode_max_pages < num_of_pages: # pragma: no cover
|
||||
logger.debug(
|
||||
f"Barcodes detection will be limited to the first {barcode_max_pages} pages",
|
||||
)
|
||||
|
||||
# Loop al page
|
||||
for current_page_number in range(min(num_of_pages, barcode_max_pages)):
|
||||
logger.debug(f"Processing page {current_page_number}")
|
||||
|
||||
# Convert page to image
|
||||
page = convert_from_path(
|
||||
self.pdf_file,
|
||||
dpi=self.settings.barcode_dpi,
|
||||
output_folder=self.temp_dir.name,
|
||||
first_page=current_page_number + 1,
|
||||
last_page=current_page_number + 1,
|
||||
)[0]
|
||||
|
||||
# Remember filename, since it is lost by upscaling
|
||||
page_filepath = Path(page.filename)
|
||||
logger.debug(f"Image is at {page_filepath}")
|
||||
|
||||
# Upscale image if configured
|
||||
factor = self.settings.barcode_upscale
|
||||
if factor > 1.0:
|
||||
logger.debug(
|
||||
f"Upscaling image by {factor} for better barcode detection",
|
||||
)
|
||||
x, y = page.size
|
||||
page = page.resize(
|
||||
(round(x * factor), (round(y * factor))),
|
||||
)
|
||||
|
||||
# Detect barcodes
|
||||
for barcode_value in self.read_barcodes_zxing(page):
|
||||
self.barcodes.append(
|
||||
Barcode(current_page_number, barcode_value, self.settings),
|
||||
)
|
||||
|
||||
# Delete temporary image file
|
||||
page_filepath.unlink()
|
||||
|
||||
# Password protected files can't be checked
|
||||
# This is the exception raised for those
|
||||
except PasswordError as e:
|
||||
@@ -478,111 +534,3 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
||||
document_paths.append(savepath)
|
||||
|
||||
return document_paths
|
||||
|
||||
|
||||
def scannable_mime_types(settings: BarcodeConfig) -> set[str]:
|
||||
"""
|
||||
The file types the barcode scan supports with the current settings
|
||||
"""
|
||||
if settings.barcode_enable_tiff_support:
|
||||
return {"application/pdf", "image/tiff"}
|
||||
return {"application/pdf"}
|
||||
|
||||
|
||||
def read_barcodes_zxing(image: Image.Image) -> list[tuple[str, str]]:
|
||||
"""
|
||||
Returns the text and format (zxing enum name) of each barcode found in
|
||||
the image
|
||||
"""
|
||||
barcodes = []
|
||||
|
||||
import zxingcpp
|
||||
|
||||
detected_barcodes = zxingcpp.read_barcodes(image)
|
||||
for barcode in detected_barcodes:
|
||||
if barcode.text:
|
||||
barcodes.append((barcode.text, barcode.format.name))
|
||||
logger.debug(
|
||||
f"Barcode of type {barcode.format} found: {barcode.text}",
|
||||
)
|
||||
|
||||
return barcodes
|
||||
|
||||
|
||||
def scan_pdf(pdf_path: Path, settings: BarcodeConfig, work_dir: Path) -> list[Barcode]:
|
||||
"""
|
||||
Scans the pages of a PDF as images for barcodes. Errors are not caught,
|
||||
so callers can tell a failed scan from one that found nothing.
|
||||
"""
|
||||
barcodes: list[Barcode] = []
|
||||
|
||||
with Pdf.open(pdf_path) as pdf:
|
||||
num_of_pages = len(pdf.pages)
|
||||
logger.debug(f"PDF has {num_of_pages} pages")
|
||||
|
||||
# Get limit from configuration
|
||||
barcode_max_pages: int = (
|
||||
num_of_pages if settings.barcode_max_pages == 0 else settings.barcode_max_pages
|
||||
)
|
||||
|
||||
if barcode_max_pages < num_of_pages: # pragma: no cover
|
||||
logger.debug(
|
||||
f"Barcodes detection will be limited to the first {barcode_max_pages} pages",
|
||||
)
|
||||
|
||||
for current_page_number in range(min(num_of_pages, barcode_max_pages)):
|
||||
logger.debug(f"Processing page {current_page_number}")
|
||||
|
||||
# Convert page to image
|
||||
page = convert_from_path(
|
||||
pdf_path,
|
||||
dpi=settings.barcode_dpi,
|
||||
output_folder=work_dir,
|
||||
first_page=current_page_number + 1,
|
||||
last_page=current_page_number + 1,
|
||||
)[0]
|
||||
|
||||
# Remember filename, since it is lost by upscaling
|
||||
page_filepath = Path(page.filename)
|
||||
logger.debug(f"Image is at {page_filepath}")
|
||||
|
||||
# Upscale image if configured
|
||||
factor = settings.barcode_upscale
|
||||
if factor > 1.0:
|
||||
logger.debug(
|
||||
f"Upscaling image by {factor} for better barcode detection",
|
||||
)
|
||||
x, y = page.size
|
||||
page = page.resize(
|
||||
(round(x * factor), (round(y * factor))),
|
||||
)
|
||||
|
||||
for barcode_value, barcode_format in read_barcodes_zxing(page):
|
||||
barcodes.append(
|
||||
Barcode(current_page_number, barcode_value, settings, barcode_format),
|
||||
)
|
||||
|
||||
# Delete temporary image file
|
||||
page_filepath.unlink()
|
||||
|
||||
return barcodes
|
||||
|
||||
|
||||
def read_barcode_values(
|
||||
path: Path,
|
||||
mime_type: str,
|
||||
settings: BarcodeConfig,
|
||||
work_dir: Path,
|
||||
) -> list[StoredBarcode] | None:
|
||||
"""
|
||||
Reads the barcodes of a file outside of the consumption plugins: for new
|
||||
versions, which skip the barcode plugin, and when reprocessing.
|
||||
|
||||
Returns None if the file can't be scanned with the current settings.
|
||||
Errors while scanning are raised.
|
||||
"""
|
||||
if mime_type not in scannable_mime_types(settings):
|
||||
return None
|
||||
if mime_type == "image/tiff":
|
||||
path = convert_from_tiff_to_pdf(path, work_dir)
|
||||
return [x.stored() for x in scan_pdf(path, settings, work_dir)]
|
||||
@@ -13,14 +13,8 @@ from celery import group
|
||||
from celery import shared_task
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.db.models import Case
|
||||
from django.db.models import F
|
||||
from django.db.models import Max
|
||||
from django.db.models import OuterRef
|
||||
from django.db.models import Q
|
||||
from django.db.models import Subquery
|
||||
from django.db.models import When
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils import timezone
|
||||
|
||||
from documents.data_models import ConsumableDocument
|
||||
@@ -42,7 +36,6 @@ from documents.tasks import remove_document_from_index
|
||||
from documents.tasks import update_document_content_maybe_archive_file
|
||||
from documents.versioning import get_latest_version_for_root
|
||||
from documents.versioning import get_root_document
|
||||
from documents.versioning import versions_newest_first
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Mapping
|
||||
@@ -415,28 +408,10 @@ def reprocess(doc_ids: list[int], *, remote_ocr: bool = False) -> Literal["OK"]:
|
||||
|
||||
Consumption workflows do not run here, so ``remote_ocr`` is how the user
|
||||
asks for the remote engine when it is not configured to handle everything.
|
||||
|
||||
A root document with versions reprocesses its latest version, which is the
|
||||
file whose content, archive and thumbnail are shown for it.
|
||||
"""
|
||||
latest_version = versions_newest_first(
|
||||
Document.objects.filter(root_document=OuterRef("pk")),
|
||||
).values("id")[:1]
|
||||
source_ids = (
|
||||
Document.objects.filter(id__in=doc_ids)
|
||||
.annotate(
|
||||
source_id=Case(
|
||||
When(root_document__isnull=False, then=F("id")),
|
||||
default=Coalesce(Subquery(latest_version), F("id")),
|
||||
),
|
||||
)
|
||||
.order_by()
|
||||
.values_list("source_id", flat=True)
|
||||
.distinct()
|
||||
)
|
||||
for source_id in source_ids:
|
||||
for document_id in doc_ids:
|
||||
update_document_content_maybe_archive_file.apply_async(
|
||||
kwargs={"document_id": source_id, "remote_ocr": remote_ocr},
|
||||
kwargs={"document_id": document_id, "remote_ocr": remote_ocr},
|
||||
headers={"trigger_source": PaperlessTask.TriggerSource.MANUAL},
|
||||
)
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ from django.utils import timezone
|
||||
from filelock import FileLock
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from documents.barcodes import read_barcode_values
|
||||
from documents.classifier import load_classifier
|
||||
from documents.data_models import ConsumableDocument
|
||||
from documents.data_models import ConsumeFileSuccessResult
|
||||
@@ -32,7 +31,6 @@ from documents.models import Correspondent
|
||||
from documents.models import CustomField
|
||||
from documents.models import CustomFieldInstance
|
||||
from documents.models import Document
|
||||
from documents.models import DocumentBarcode
|
||||
from documents.models import DocumentType
|
||||
from documents.models import StoragePath
|
||||
from documents.models import Tag
|
||||
@@ -55,7 +53,6 @@ from documents.utils import compute_checksum
|
||||
from documents.utils import copy_basic_file_stats
|
||||
from documents.utils import copy_file_with_basic_stats
|
||||
from documents.utils import run_subprocess
|
||||
from paperless.config import BarcodeConfig
|
||||
from paperless.config import OcrConfig
|
||||
from paperless.config import RemoteOCRConfig
|
||||
from paperless.models import ArchiveFileGenerationChoices
|
||||
@@ -507,13 +504,6 @@ class ConsumerPlugin(
|
||||
f"Parser: {document_parser.name} v{document_parser.version}",
|
||||
)
|
||||
|
||||
# New versions skip the barcode plugin, so read their barcodes here
|
||||
if (
|
||||
self.input_doc.root_document_id is not None
|
||||
and self.metadata.barcodes is None
|
||||
):
|
||||
self._read_version_barcodes(mime_type, Path(tmpdir))
|
||||
|
||||
# Parse the document. This may take some time.
|
||||
|
||||
text = None
|
||||
@@ -641,8 +631,6 @@ class ConsumerPlugin(
|
||||
else:
|
||||
original_document.save()
|
||||
|
||||
self._store_barcodes(original_document)
|
||||
|
||||
# Adding a version changes the effective document, so update root modified
|
||||
Document.objects.filter(pk=root_doc.pk).update(
|
||||
modified=timezone.now(),
|
||||
@@ -974,32 +962,6 @@ class ConsumerPlugin(
|
||||
}
|
||||
CustomFieldInstance.objects.create(**args) # adds to document
|
||||
|
||||
self._store_barcodes(document)
|
||||
|
||||
def _read_version_barcodes(self, mime_type: str, work_dir: Path) -> None:
|
||||
barcode_settings = BarcodeConfig()
|
||||
if not barcode_settings.barcode_store_values:
|
||||
return
|
||||
try:
|
||||
self.metadata.barcodes = (
|
||||
read_barcode_values(
|
||||
self.working_copy,
|
||||
mime_type,
|
||||
barcode_settings,
|
||||
work_dir,
|
||||
)
|
||||
or None
|
||||
)
|
||||
except Exception as e:
|
||||
self.log.warning(f"Could not read barcodes of {self.filename}: {e}")
|
||||
|
||||
def _store_barcodes(self, document: Document) -> None:
|
||||
if self.metadata.barcodes:
|
||||
DocumentBarcode.objects.bulk_create(
|
||||
DocumentBarcode(document=document, **barcode)
|
||||
for barcode in self.metadata.barcodes
|
||||
)
|
||||
|
||||
def _write(self, source, target) -> None:
|
||||
with (
|
||||
Path(source).open("rb") as read_file,
|
||||
|
||||
@@ -9,16 +9,6 @@ from guardian.shortcuts import get_groups_with_perms
|
||||
from guardian.shortcuts import get_users_with_perms
|
||||
|
||||
|
||||
class StoredBarcode(TypedDict):
|
||||
"""
|
||||
A detected barcode as it is stored with a document
|
||||
"""
|
||||
|
||||
page: int # 1-indexed
|
||||
value: str
|
||||
format: str # a DocumentBarcode.Format value
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class DocumentMetadataOverrides:
|
||||
"""
|
||||
@@ -45,7 +35,6 @@ class DocumentMetadataOverrides:
|
||||
version_label: str | None = None
|
||||
actor_id: int | None = None
|
||||
remote_ocr: bool = False
|
||||
barcodes: list[StoredBarcode] | None = None
|
||||
|
||||
def update(self, other: "DocumentMetadataOverrides") -> "DocumentMetadataOverrides":
|
||||
"""
|
||||
|
||||
@@ -45,7 +45,6 @@ from documents.models import Correspondent
|
||||
from documents.models import CustomField
|
||||
from documents.models import CustomFieldInstance
|
||||
from documents.models import Document
|
||||
from documents.models import DocumentBarcode
|
||||
from documents.models import DocumentType
|
||||
from documents.models import Note
|
||||
from documents.models import SavedView
|
||||
@@ -354,7 +353,6 @@ class Command(CryptMixin, PaperlessCommand):
|
||||
"workflows": Workflow.objects.all(),
|
||||
"custom_fields": CustomField.objects.all(),
|
||||
"custom_field_instances": CustomFieldInstance.global_objects.all(),
|
||||
"document_barcodes": DocumentBarcode.objects.all(),
|
||||
"app_configs": ApplicationConfiguration.objects.all(),
|
||||
"notes": Note.global_objects.all(),
|
||||
"documents": Document.global_objects.order_by("id").all(),
|
||||
@@ -413,7 +411,6 @@ class Command(CryptMixin, PaperlessCommand):
|
||||
elif self.split_manifest and key in (
|
||||
"notes",
|
||||
"custom_field_instances",
|
||||
"document_barcodes",
|
||||
):
|
||||
# Written per-document in _write_split_manifest
|
||||
pass
|
||||
@@ -654,12 +651,6 @@ class Command(CryptMixin, PaperlessCommand):
|
||||
CustomFieldInstance.global_objects.filter(document=document),
|
||||
),
|
||||
)
|
||||
content.extend(
|
||||
serializers.serialize(
|
||||
"python",
|
||||
DocumentBarcode.objects.filter(document=document),
|
||||
),
|
||||
)
|
||||
manifest_name = base_name.with_name(f"{base_name.stem}-manifest.json")
|
||||
if self.use_folder_prefix:
|
||||
manifest_name = Path("json") / manifest_name
|
||||
|
||||
@@ -77,8 +77,6 @@ class Command(PaperlessCommand):
|
||||
"notes__user",
|
||||
"custom_fields__field",
|
||||
"versions",
|
||||
"barcodes",
|
||||
"versions__barcodes",
|
||||
)
|
||||
total = documents.count()
|
||||
rebuild_kwargs = {}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
# Generated by Django 5.2.16 on 2026-09-30 23:01
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("documents", "0026_alter_document_archive_checksum_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="DocumentBarcode",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"page",
|
||||
models.PositiveIntegerField(
|
||||
help_text="Page of the original file, starting at 1",
|
||||
verbose_name="page",
|
||||
),
|
||||
),
|
||||
("value", models.TextField(verbose_name="value")),
|
||||
(
|
||||
"format",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("Codabar", "Codabar"),
|
||||
("Code39", "Code 39"),
|
||||
("Code39Std", "Code 39 Standard"),
|
||||
("Code39Ext", "Code 39 Extended"),
|
||||
("Code32", "Code 32"),
|
||||
("PZN", "Pharmazentralnummer"),
|
||||
("Code93", "Code 93"),
|
||||
("Code128", "Code 128"),
|
||||
("ITF", "ITF"),
|
||||
("ITF14", "ITF-14"),
|
||||
("DataBar", "DataBar"),
|
||||
("DataBarOmni", "DataBar Omni"),
|
||||
("DataBarStk", "DataBar Stacked"),
|
||||
("DataBarStkOmni", "DataBar Stacked Omni"),
|
||||
("DataBarLtd", "DataBar Limited"),
|
||||
("DataBarExp", "DataBar Expanded"),
|
||||
("DataBarExpStk", "DataBar Expanded Stacked"),
|
||||
("EANUPC", "EAN/UPC"),
|
||||
("EAN13", "EAN-13"),
|
||||
("EAN8", "EAN-8"),
|
||||
("EAN5", "EAN-5"),
|
||||
("EAN2", "EAN-2"),
|
||||
("ISBN", "ISBN"),
|
||||
("UPCA", "UPC-A"),
|
||||
("UPCE", "UPC-E"),
|
||||
("Telepen", "Telepen"),
|
||||
("TelepenAlpha", "Telepen Alpha"),
|
||||
("TelepenNumeric", "Telepen Numeric"),
|
||||
("OtherBarcode", "Other barcode"),
|
||||
("DXFilmEdge", "DX Film Edge"),
|
||||
("PDF417", "PDF417"),
|
||||
("CompactPDF417", "Compact PDF417"),
|
||||
("MicroPDF417", "MicroPDF417"),
|
||||
("Aztec", "Aztec"),
|
||||
("AztecCode", "Aztec Code"),
|
||||
("AztecRune", "Aztec Rune"),
|
||||
("QRCode", "QR Code"),
|
||||
("QRCodeModel1", "QR Code Model 1"),
|
||||
("QRCodeModel2", "QR Code Model 2"),
|
||||
("MicroQRCode", "Micro QR Code"),
|
||||
("RMQRCode", "rMQR Code"),
|
||||
("DataMatrix", "Data Matrix"),
|
||||
("MaxiCode", "MaxiCode"),
|
||||
],
|
||||
max_length=32,
|
||||
verbose_name="format",
|
||||
),
|
||||
),
|
||||
(
|
||||
"document",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="barcodes",
|
||||
to="documents.document",
|
||||
verbose_name="document",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "document barcode",
|
||||
"verbose_name_plural": "document barcodes",
|
||||
"ordering": ("page", "id"),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -366,16 +366,6 @@ class Document(SoftDeleteModel, ModelWithOwner): # type: ignore[django-manager-
|
||||
res += f" {self.title}"
|
||||
return res
|
||||
|
||||
def get_effective_barcodes(self) -> list["DocumentBarcode"]:
|
||||
"""
|
||||
Returns the stored barcodes for the document, like
|
||||
get_effective_content(): for root documents those of the latest
|
||||
version when there is one, as that is the file users see.
|
||||
"""
|
||||
from documents.versioning import latest_version
|
||||
|
||||
return list(latest_version(self).barcodes.all())
|
||||
|
||||
def get_effective_content(self) -> str | None:
|
||||
"""
|
||||
Returns the effective content for the document.
|
||||
@@ -979,87 +969,6 @@ class Note(SoftDeleteModel):
|
||||
return self.note
|
||||
|
||||
|
||||
class DocumentBarcode(models.Model):
|
||||
"""
|
||||
A barcode found in a document during consumption, kept so its content
|
||||
can be shown and copied
|
||||
"""
|
||||
|
||||
document = models.ForeignKey(
|
||||
Document,
|
||||
related_name="barcodes",
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_("document"),
|
||||
)
|
||||
|
||||
page = models.PositiveIntegerField(
|
||||
_("page"),
|
||||
help_text=_("Page of the original file, starting at 1"),
|
||||
)
|
||||
|
||||
value = models.TextField(_("value"))
|
||||
|
||||
class Format(models.TextChoices):
|
||||
"""
|
||||
The concrete barcode formats of zxing-cpp, keyed on the enum name.
|
||||
The labels are symbology names and aren't translated.
|
||||
"""
|
||||
|
||||
CODABAR = "Codabar", "Codabar"
|
||||
CODE39 = "Code39", "Code 39"
|
||||
CODE39_STD = "Code39Std", "Code 39 Standard"
|
||||
CODE39_EXT = "Code39Ext", "Code 39 Extended"
|
||||
CODE32 = "Code32", "Code 32"
|
||||
PZN = "PZN", "Pharmazentralnummer"
|
||||
CODE93 = "Code93", "Code 93"
|
||||
CODE128 = "Code128", "Code 128"
|
||||
ITF = "ITF", "ITF"
|
||||
ITF14 = "ITF14", "ITF-14"
|
||||
DATA_BAR = "DataBar", "DataBar"
|
||||
DATA_BAR_OMNI = "DataBarOmni", "DataBar Omni"
|
||||
DATA_BAR_STK = "DataBarStk", "DataBar Stacked"
|
||||
DATA_BAR_STK_OMNI = "DataBarStkOmni", "DataBar Stacked Omni"
|
||||
DATA_BAR_LTD = "DataBarLtd", "DataBar Limited"
|
||||
DATA_BAR_EXP = "DataBarExp", "DataBar Expanded"
|
||||
DATA_BAR_EXP_STK = "DataBarExpStk", "DataBar Expanded Stacked"
|
||||
EANUPC = "EANUPC", "EAN/UPC"
|
||||
EAN13 = "EAN13", "EAN-13"
|
||||
EAN8 = "EAN8", "EAN-8"
|
||||
EAN5 = "EAN5", "EAN-5"
|
||||
EAN2 = "EAN2", "EAN-2"
|
||||
ISBN = "ISBN", "ISBN"
|
||||
UPCA = "UPCA", "UPC-A"
|
||||
UPCE = "UPCE", "UPC-E"
|
||||
TELEPEN = "Telepen", "Telepen"
|
||||
TELEPEN_ALPHA = "TelepenAlpha", "Telepen Alpha"
|
||||
TELEPEN_NUMERIC = "TelepenNumeric", "Telepen Numeric"
|
||||
OTHER_BARCODE = "OtherBarcode", "Other barcode"
|
||||
DX_FILM_EDGE = "DXFilmEdge", "DX Film Edge"
|
||||
PDF417 = "PDF417", "PDF417"
|
||||
COMPACT_PDF417 = "CompactPDF417", "Compact PDF417"
|
||||
MICRO_PDF417 = "MicroPDF417", "MicroPDF417"
|
||||
AZTEC = "Aztec", "Aztec"
|
||||
AZTEC_CODE = "AztecCode", "Aztec Code"
|
||||
AZTEC_RUNE = "AztecRune", "Aztec Rune"
|
||||
QR_CODE = "QRCode", "QR Code"
|
||||
QR_CODE_MODEL1 = "QRCodeModel1", "QR Code Model 1"
|
||||
QR_CODE_MODEL2 = "QRCodeModel2", "QR Code Model 2"
|
||||
MICRO_QR_CODE = "MicroQRCode", "Micro QR Code"
|
||||
RMQR_CODE = "RMQRCode", "rMQR Code"
|
||||
DATA_MATRIX = "DataMatrix", "Data Matrix"
|
||||
MAXI_CODE = "MaxiCode", "MaxiCode"
|
||||
|
||||
format = models.CharField(_("format"), max_length=32, choices=Format.choices)
|
||||
|
||||
class Meta:
|
||||
ordering = ("page", "id")
|
||||
verbose_name = _("document barcode")
|
||||
verbose_name_plural = _("document barcodes")
|
||||
|
||||
def __str__(self) -> str: # pragma: no cover
|
||||
return self.value
|
||||
|
||||
|
||||
class ShareLink(SoftDeleteModel):
|
||||
class FileVersion(models.TextChoices):
|
||||
ARCHIVE = ("archive", _("Archive"))
|
||||
|
||||
@@ -6,9 +6,7 @@ from django.contrib.auth.models import Permission
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import Case
|
||||
from django.db.models import CharField
|
||||
from django.db.models import Count
|
||||
from django.db.models import F
|
||||
from django.db.models import IntegerField
|
||||
from django.db.models import Model
|
||||
from django.db.models import Q
|
||||
@@ -16,7 +14,6 @@ from django.db.models import QuerySet
|
||||
from django.db.models import Value
|
||||
from django.db.models import When
|
||||
from django.db.models.functions import Cast
|
||||
from django.db.models.functions import Coalesce
|
||||
from guardian.core import ObjectPermissionChecker
|
||||
from guardian.models import GroupObjectPermission
|
||||
from guardian.models import UserObjectPermission
|
||||
@@ -351,7 +348,6 @@ def permitted_object_ids(
|
||||
perm: str,
|
||||
*,
|
||||
include_deleted: bool = False,
|
||||
parent_field: str | None = None,
|
||||
) -> QuerySet[int]:
|
||||
"""
|
||||
Generic version of ``permitted_document_ids`` for any model with an
|
||||
@@ -360,24 +356,6 @@ def permitted_object_ids(
|
||||
soft-delete pattern (currently only ``Document``); for every other model
|
||||
it is accepted but has no effect, since those models have no soft-delete
|
||||
concept.
|
||||
|
||||
``parent_field`` names a self-referencing foreign key whose target
|
||||
authorizes the row (``Document.root_document``). A row with a parent is
|
||||
visible exactly when its parent is, judged by the parent's owner and
|
||||
grants, so the row's own owner and grants are ignored.
|
||||
|
||||
Guardian stores ``object_pk`` as a string, so the row key is cast to a
|
||||
string and tested against the user's and groups' grants with a single
|
||||
uncorrelated ``IN``. Postgres and SQLite build that set once. MariaDB
|
||||
evaluates it as an index probe per row, which is cheap because the
|
||||
lookups use guardian's unique indexes. Casting every ``object_pk`` to an
|
||||
integer instead cannot use an index, and MariaDB cannot materialize it
|
||||
inside the owner ``OR``, so it re-scans the user's grants for every row.
|
||||
A correlated ``EXISTS`` per grant fixes MariaDB too, but Postgres and
|
||||
SQLite re-run it for every row and end up slower than the original. The
|
||||
user's groups are matched with an ``IN`` subquery rather than a join
|
||||
through the membership table, which SQLite plans badly once the grant
|
||||
tables grow.
|
||||
"""
|
||||
has_soft_delete = hasattr(model, "global_objects")
|
||||
manager = (
|
||||
@@ -385,21 +363,8 @@ def permitted_object_ids(
|
||||
)
|
||||
base_qs = manager.all().only("id", "owner")
|
||||
|
||||
owner_field, key_field = "owner", "pk"
|
||||
if parent_field is not None:
|
||||
owner_field, key_field = "authorizing_owner", "authorizing_id"
|
||||
base_qs = base_qs.annotate(
|
||||
authorizing_id=Coalesce(f"{parent_field}_id", "id"),
|
||||
authorizing_owner=Case(
|
||||
When(**{f"{parent_field}_id__isnull": True}, then=F("owner_id")),
|
||||
default=F(f"{parent_field}__owner_id"),
|
||||
output_field=IntegerField(),
|
||||
),
|
||||
)
|
||||
unowned = Q(**{f"{owner_field}__isnull": True})
|
||||
|
||||
if user is None or not getattr(user, "is_authenticated", False):
|
||||
return base_qs.filter(unowned).values_list("id", flat=True)
|
||||
return base_qs.filter(owner__isnull=True).values_list("id", flat=True)
|
||||
|
||||
# Deactivated users get nothing, deactivated superusers included, so this
|
||||
# has to come before the superuser shortcut. guardian's
|
||||
@@ -423,26 +388,21 @@ def permitted_object_ids(
|
||||
"permission__content_type": content_type,
|
||||
}
|
||||
|
||||
# Both grant sets are compared to the row key as strings, exactly as
|
||||
# guardian stores them, and are uncorrelated, so each engine can build the
|
||||
# set once instead of probing per row.
|
||||
user_keys = UserObjectPermission.objects.filter(
|
||||
user=user,
|
||||
**perm_filter,
|
||||
).values_list("object_pk", flat=True)
|
||||
group_keys = GroupObjectPermission.objects.filter(
|
||||
group_id__in=user.groups.values("id"),
|
||||
**perm_filter,
|
||||
).values_list("object_pk", flat=True)
|
||||
permitted_keys = user_keys.union(group_keys, all=True)
|
||||
|
||||
return (
|
||||
base_qs.annotate(permitted_key=Cast(key_field, CharField(max_length=64)))
|
||||
.filter(
|
||||
Q(**{owner_field: user.pk}) | unowned | Q(permitted_key__in=permitted_keys),
|
||||
)
|
||||
.values_list("id", flat=True)
|
||||
user_perm_ids = (
|
||||
UserObjectPermission.objects.filter(user=user, **perm_filter)
|
||||
.annotate(object_pk_int=Cast("object_pk", IntegerField()))
|
||||
.values_list("object_pk_int", flat=True)
|
||||
)
|
||||
group_perm_ids = (
|
||||
GroupObjectPermission.objects.filter(group__user=user, **perm_filter)
|
||||
.annotate(object_pk_int=Cast("object_pk", IntegerField()))
|
||||
.values_list("object_pk_int", flat=True)
|
||||
)
|
||||
permitted_ids = user_perm_ids.union(group_perm_ids)
|
||||
|
||||
return base_qs.filter(
|
||||
Q(owner=user) | Q(owner__isnull=True) | Q(id__in=permitted_ids),
|
||||
).values_list("id", flat=True)
|
||||
|
||||
|
||||
ModelT = TypeVar("ModelT", bound=Model)
|
||||
@@ -510,17 +470,8 @@ def permitted_document_ids(
|
||||
``include_deleted=True`` for callers that need to check permission on
|
||||
soft-deleted documents (e.g. trash restore). This intentionally avoids
|
||||
``get_objects_for_user`` to keep the subquery small and index-friendly.
|
||||
|
||||
A version is authorized by its root document, so a version's own owner and
|
||||
grants never matter.
|
||||
"""
|
||||
return permitted_object_ids(
|
||||
user,
|
||||
Document,
|
||||
perm,
|
||||
include_deleted=include_deleted,
|
||||
parent_field="root_document",
|
||||
)
|
||||
return permitted_object_ids(user, Document, perm, include_deleted=include_deleted)
|
||||
|
||||
|
||||
def get_document_count_filter_for_user(user, related_name: str = "documents"):
|
||||
|
||||
Loaded 100 of 228 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user