mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-08-14 00:26:21 +00:00
Compare commits
4 Commits
feature-re
...
feature-tr
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1f8c60a108 | ||
![]() |
ee6b700243 | ||
![]() |
b1a84c65ed | ||
![]() |
edb8c06e2a |
@@ -1,3 +0,0 @@
|
|||||||
[codespell]
|
|
||||||
write-changes = True
|
|
||||||
ignore-words-list = criterias,afterall,valeu,ureue,equest,ure,assertIn
|
|
@@ -31,7 +31,6 @@ repos:
|
|||||||
rev: v2.4.1
|
rev: v2.4.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: codespell
|
- id: codespell
|
||||||
exclude: "(^src-ui/src/locale/)|(^src-ui/pnpm-lock.yaml)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)|(^src/documents/tests/samples/)"
|
|
||||||
exclude_types:
|
exclude_types:
|
||||||
- pofile
|
- pofile
|
||||||
- json
|
- json
|
||||||
|
18
Dockerfile
18
Dockerfile
@@ -5,7 +5,7 @@
|
|||||||
# Purpose: Compiles the frontend
|
# Purpose: Compiles the frontend
|
||||||
# Notes:
|
# Notes:
|
||||||
# - Does PNPM stuff with Typescript and such
|
# - Does PNPM stuff with Typescript and such
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/node:20-bookworm-slim AS compile-frontend
|
FROM --platform=$BUILDPLATFORM docker.io/node:20-trixie-slim AS compile-frontend
|
||||||
|
|
||||||
COPY ./src-ui /src/src-ui
|
COPY ./src-ui /src/src-ui
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ RUN set -eux \
|
|||||||
# Purpose: Installs s6-overlay and rootfs
|
# Purpose: Installs s6-overlay and rootfs
|
||||||
# Comments:
|
# Comments:
|
||||||
# - Don't leave anything extra in here either
|
# - Don't leave anything extra in here either
|
||||||
FROM ghcr.io/astral-sh/uv:0.8.4-python3.12-bookworm-slim AS s6-overlay-base
|
FROM ghcr.io/astral-sh/uv:0.8.8-python3.12-trixie-slim AS s6-overlay-base
|
||||||
|
|
||||||
WORKDIR /usr/src/s6
|
WORKDIR /usr/src/s6
|
||||||
|
|
||||||
@@ -170,20 +170,8 @@ RUN set -eux \
|
|||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \
|
&& apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \
|
||||||
&& echo "Installing pre-built updates" \
|
&& echo "Installing pre-built updates" \
|
||||||
&& curl --fail --silent --no-progress-meter --show-error --location --remote-name-all --parallel --parallel-max 4 \
|
&& curl --fail --silent --no-progress-meter --show-error --location --remote-name-all \
|
||||||
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
||||||
&& echo "Installing qpdf ${QPDF_VERSION}" \
|
|
||||||
&& dpkg --install ./libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
|
||||||
&& dpkg --install ./qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
|
||||||
&& echo "Installing Ghostscript ${GS_VERSION}" \
|
|
||||||
&& dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
|
|
||||||
&& dpkg --install ./libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
|
||||||
&& dpkg --install ./ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
|
||||||
&& echo "Installing jbig2enc" \
|
&& echo "Installing jbig2enc" \
|
||||||
&& dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
&& dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
||||||
&& echo "Configuring imagemagick" \
|
&& echo "Configuring imagemagick" \
|
||||||
|
319
dev.txt
Normal file
319
dev.txt
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
adduser 3.134
|
||||||
|
apt 2.6.1
|
||||||
|
base-files 12.4+deb12u11
|
||||||
|
base-passwd 3.6.1
|
||||||
|
bash 5.2.15-2+b8
|
||||||
|
bsdutils 1:2.38.1-5+deb12u3
|
||||||
|
ca-certificates 20230311+deb12u1
|
||||||
|
coreutils 9.1-1
|
||||||
|
curl 7.88.1-10+deb12u12
|
||||||
|
dash 0.5.12-2
|
||||||
|
debconf 1.5.82
|
||||||
|
debian-archive-keyring 2023.3+deb12u2
|
||||||
|
debianutils 5.7-0.5~deb12u1
|
||||||
|
diffutils 1:3.8-4
|
||||||
|
dirmngr 2.2.40-1.1
|
||||||
|
dpkg 1.21.22
|
||||||
|
e2fsprogs 1.47.0-2
|
||||||
|
file 1:5.44-3
|
||||||
|
findutils 4.9.0-4
|
||||||
|
fontconfig 2.14.1-4
|
||||||
|
fontconfig-config 2.14.1-4
|
||||||
|
fonts-liberation 1:1.07.4-11
|
||||||
|
fonts-urw-base35 20200910-7
|
||||||
|
gcc-12-base 12.2.0-14+deb12u1
|
||||||
|
gettext 0.21-12
|
||||||
|
gettext-base 0.21-12
|
||||||
|
ghostscript 10.03.1~dfsg-1
|
||||||
|
gnupg 2.2.40-1.1
|
||||||
|
gnupg-l10n 2.2.40-1.1
|
||||||
|
gnupg-utils 2.2.40-1.1
|
||||||
|
gosu 1.14-1+b10
|
||||||
|
gpg 2.2.40-1.1
|
||||||
|
gpg-agent 2.2.40-1.1
|
||||||
|
gpg-wks-client 2.2.40-1.1
|
||||||
|
gpg-wks-server 2.2.40-1.1
|
||||||
|
gpgconf 2.2.40-1.1
|
||||||
|
gpgsm 2.2.40-1.1
|
||||||
|
gpgv 2.2.40-1.1
|
||||||
|
grep 3.8-5
|
||||||
|
gzip 1.12-1
|
||||||
|
hicolor-icon-theme 0.17-2
|
||||||
|
hostname 3.23+nmu1
|
||||||
|
icc-profiles-free 2.0.1+dfsg-1.1
|
||||||
|
imagemagick 8:6.9.11.60+dfsg-1.6+deb12u3
|
||||||
|
imagemagick-6-common 8:6.9.11.60+dfsg-1.6+deb12u3
|
||||||
|
imagemagick-6.q16 8:6.9.11.60+dfsg-1.6+deb12u3
|
||||||
|
init-system-helpers 1.65.2
|
||||||
|
jbig2dec 0.19-3
|
||||||
|
jbig2enc 0.30-1
|
||||||
|
libacl1 2.3.1-3
|
||||||
|
libaom3 3.6.0-1+deb12u1
|
||||||
|
libapt-pkg6.0 2.6.1
|
||||||
|
libarchive13 3.6.2-1+deb12u2
|
||||||
|
libassuan0 2.5.5-5
|
||||||
|
libattr1 1:2.5.1-4
|
||||||
|
libaudit-common 1:3.0.9-1
|
||||||
|
libaudit1 1:3.0.9-1
|
||||||
|
libavahi-client3 0.8-10+deb12u1
|
||||||
|
libavahi-common-data 0.8-10+deb12u1
|
||||||
|
libavahi-common3 0.8-10+deb12u1
|
||||||
|
libavcodec59 7:5.1.6-0+deb12u1
|
||||||
|
libavformat59 7:5.1.6-0+deb12u1
|
||||||
|
libavutil57 7:5.1.6-0+deb12u1
|
||||||
|
libblkid1 2.38.1-5+deb12u3
|
||||||
|
libbluray2 1:1.3.4-1
|
||||||
|
libbrotli1 1.0.9-2+b6
|
||||||
|
libbsd0 0.11.7-2
|
||||||
|
libbz2-1.0 1.0.8-5+b1
|
||||||
|
libc-bin 2.36-9+deb12u10
|
||||||
|
libc6 2.36-9+deb12u10
|
||||||
|
libcairo-gobject2 1.16.0-7
|
||||||
|
libcairo2 1.16.0-7
|
||||||
|
libcap-ng0 0.8.3-1+b3
|
||||||
|
libcap2 1:2.66-4+deb12u1
|
||||||
|
libchromaprint1 1.5.1-2+b1
|
||||||
|
libcjson1 1.7.15-1+deb12u2
|
||||||
|
libcodec2-1.0 1.0.5-1
|
||||||
|
libcom-err2 1.47.0-2
|
||||||
|
libconfig-inifiles-perl 3.000003-2
|
||||||
|
libcrypt1 1:4.4.33-2
|
||||||
|
libcups2 2.4.2-3+deb12u8
|
||||||
|
libcurl4 7.88.1-10+deb12u12
|
||||||
|
libdatrie1 0.2.13-2+b1
|
||||||
|
libdav1d6 1.0.0-2+deb12u1
|
||||||
|
libdb5.3 5.3.28+dfsg2-1
|
||||||
|
libdbus-1-3 1.14.10-1~deb12u1
|
||||||
|
libde265-0 1.0.11-1+deb12u2
|
||||||
|
libdebconfclient0 0.270
|
||||||
|
libdeflate0 1.14-1
|
||||||
|
libdrm-common 2.4.114-1
|
||||||
|
libdrm2 2.4.114-1+b1
|
||||||
|
libedit2 3.1-20221030-2
|
||||||
|
libexpat1 2.5.0-1+deb12u1
|
||||||
|
libext2fs2 1.47.0-2
|
||||||
|
libffi8 3.4.4-1
|
||||||
|
libfftw3-double3 3.3.10-1
|
||||||
|
libfontconfig1 2.14.1-4
|
||||||
|
libfontenc1 1:1.1.4-1
|
||||||
|
libfreetype6 2.12.1+dfsg-5+deb12u4
|
||||||
|
libfribidi0 1.0.8-2.1
|
||||||
|
libgcc-s1 12.2.0-14+deb12u1
|
||||||
|
libgcrypt20 1.10.1-3
|
||||||
|
libgdbm-compat4 1.23-3
|
||||||
|
libgdbm6 1.23-3
|
||||||
|
libgdk-pixbuf-2.0-0 2.42.10+dfsg-1+deb12u2
|
||||||
|
libgdk-pixbuf2.0-common 2.42.10+dfsg-1+deb12u2
|
||||||
|
libgif7 5.2.1-2.5
|
||||||
|
libglib2.0-0 2.74.6-2+deb12u6
|
||||||
|
libgme0 0.6.3-6
|
||||||
|
libgmp10 2:6.2.1+dfsg1-1.1
|
||||||
|
libgnutls30 3.7.9-2+deb12u5
|
||||||
|
libgomp1 12.2.0-14+deb12u1
|
||||||
|
libgpg-error0 1.46-1
|
||||||
|
libgraphite2-3 1.3.14-1
|
||||||
|
libgs-common 10.0.0~dfsg-11+deb12u7
|
||||||
|
libgs10 10.03.1~dfsg-1
|
||||||
|
libgs10-common 10.03.1~dfsg-1
|
||||||
|
libgsm1 1.0.22-1
|
||||||
|
libgssapi-krb5-2 1.20.1-2+deb12u3
|
||||||
|
libharfbuzz0b 6.0.0+dfsg-3
|
||||||
|
libheif1 1.15.1-1+deb12u1
|
||||||
|
libhogweed6 3.8.1-2
|
||||||
|
libhwy1 1.0.3-3+deb12u1
|
||||||
|
libice6 2:1.0.10-1
|
||||||
|
libicu72 72.1-3+deb12u1
|
||||||
|
libidn12 1.41-1
|
||||||
|
libidn2-0 2.3.3-1+b1
|
||||||
|
libijs-0.35 0.35-15
|
||||||
|
libimagequant0 2.17.0-1
|
||||||
|
libjbig0 2.1-6.1
|
||||||
|
libjbig2dec0 0.19-3
|
||||||
|
libjpeg62-turbo 1:2.1.5-2
|
||||||
|
libjxl0.7 0.7.0-10+deb12u1
|
||||||
|
libk5crypto3 1.20.1-2+deb12u3
|
||||||
|
libkeyutils1 1.6.3-2
|
||||||
|
libkrb5-3 1.20.1-2+deb12u3
|
||||||
|
libkrb5support0 1.20.1-2+deb12u3
|
||||||
|
libksba8 1.6.3-2
|
||||||
|
liblcms2-2 2.14-2
|
||||||
|
libldap-2.5-0 2.5.13+dfsg-5
|
||||||
|
liblept5 1.82.0-3+b3
|
||||||
|
liblerc4 4.0.0+ds-2
|
||||||
|
liblqr-1-0 0.4.2-2.1
|
||||||
|
libltdl7 2.4.7-7~deb12u1
|
||||||
|
liblz4-1 1.9.4-1
|
||||||
|
liblzma5 5.4.1-1
|
||||||
|
libmagic-mgc 1:5.44-3
|
||||||
|
libmagic1 1:5.44-3
|
||||||
|
libmagickcore-6.q16-6 8:6.9.11.60+dfsg-1.6+deb12u3
|
||||||
|
libmagickwand-6.q16-6 8:6.9.11.60+dfsg-1.6+deb12u3
|
||||||
|
libmariadb3 1:10.11.11-0+deb12u1
|
||||||
|
libmbedcrypto7 2.28.3-1
|
||||||
|
libmd0 1.0.4-2
|
||||||
|
libmfx1 22.5.4-1
|
||||||
|
libmount1 2.38.1-5+deb12u3
|
||||||
|
libmp3lame0 3.100-6
|
||||||
|
libmpg123-0 1.31.2-1+deb12u1
|
||||||
|
libncurses6 6.4-4
|
||||||
|
libncursesw6 6.4-4
|
||||||
|
libnettle8 3.8.1-2
|
||||||
|
libnghttp2-14 1.52.0-1+deb12u2
|
||||||
|
libnorm1 1.5.9+dfsg-2
|
||||||
|
libnpth0 1.6-3
|
||||||
|
libnsl2 1.3.0-2
|
||||||
|
libnspr4 2:4.35-1
|
||||||
|
libnss3 2:3.87.1-1+deb12u1
|
||||||
|
libnuma1 2.0.16-1
|
||||||
|
libogg0 1.3.5-3
|
||||||
|
libopenjp2-7 2.5.0-2+deb12u1
|
||||||
|
libopenmpt0 0.6.9-1
|
||||||
|
libopus0 1.3.1-3
|
||||||
|
libp11-kit0 0.24.1-2
|
||||||
|
libpam-modules 1.5.2-6+deb12u1
|
||||||
|
libpam-modules-bin 1.5.2-6+deb12u1
|
||||||
|
libpam-runtime 1.5.2-6+deb12u1
|
||||||
|
libpam0g 1.5.2-6+deb12u1
|
||||||
|
libpango-1.0-0 1.50.12+ds-1
|
||||||
|
libpangocairo-1.0-0 1.50.12+ds-1
|
||||||
|
libpangoft2-1.0-0 1.50.12+ds-1
|
||||||
|
libpaper1 1.1.29
|
||||||
|
libpcre2-8-0 10.42-1
|
||||||
|
libperl5.36 5.36.0-7+deb12u2
|
||||||
|
libpgm-5.3-0 5.3.128~dfsg-2
|
||||||
|
libpixman-1-0 0.42.2-1
|
||||||
|
libpng16-16 1.6.39-2
|
||||||
|
libpoppler126 22.12.0-2+deb12u1
|
||||||
|
libpq5 15.13-0+deb12u1
|
||||||
|
libpsl5 0.21.2-1
|
||||||
|
libqpdf29 11.9.0-1
|
||||||
|
librabbitmq4 0.11.0-1+deb12u1
|
||||||
|
librav1e0 0.5.1-6
|
||||||
|
libreadline8 8.2-1.3
|
||||||
|
librist4 0.2.7+dfsg-1
|
||||||
|
librsvg2-2 2.54.7+dfsg-1~deb12u1
|
||||||
|
librtmp1 2.4+20151223.gitfa8646d.1-2+b2
|
||||||
|
libsasl2-2 2.1.28+dfsg-10
|
||||||
|
libsasl2-modules-db 2.1.28+dfsg-10
|
||||||
|
libseccomp2 2.5.4-1+deb12u1
|
||||||
|
libselinux1 3.4-1+b6
|
||||||
|
libsemanage-common 3.4-1
|
||||||
|
libsemanage2 3.4-1+b5
|
||||||
|
libsepol2 3.4-2.1
|
||||||
|
libshine3 3.1.1-2
|
||||||
|
libsm6 2:1.2.3-1
|
||||||
|
libsmartcols1 2.38.1-5+deb12u3
|
||||||
|
libsnappy1v5 1.1.9-3
|
||||||
|
libsodium23 1.0.18-1
|
||||||
|
libsoxr0 0.1.3-4
|
||||||
|
libspeex1 1.2.1-2
|
||||||
|
libsqlite3-0 3.40.1-2+deb12u1
|
||||||
|
libsrt1.5-gnutls 1.5.1-1+deb12u1
|
||||||
|
libss2 1.47.0-2
|
||||||
|
libssh-gcrypt-4 0.10.6-0+deb12u1
|
||||||
|
libssh2-1 1.10.0-3+b1
|
||||||
|
libssl3 3.0.17-1~deb12u1
|
||||||
|
libstdc++6 12.2.0-14+deb12u1
|
||||||
|
libsvtav1enc1 1.4.1+dfsg-1
|
||||||
|
libswresample4 7:5.1.6-0+deb12u1
|
||||||
|
libsystemd0 252.38-1~deb12u1
|
||||||
|
libtasn1-6 4.19.0-2+deb12u1
|
||||||
|
libtesseract5 5.3.0-2
|
||||||
|
libthai-data 0.1.29-1
|
||||||
|
libthai0 0.1.29-1
|
||||||
|
libtheora0 1.1.1+dfsg.1-16.1+b1
|
||||||
|
libtiff6 4.5.0-6+deb12u2
|
||||||
|
libtinfo6 6.4-4
|
||||||
|
libtirpc-common 1.3.3+ds-1
|
||||||
|
libtirpc3 1.3.3+ds-1
|
||||||
|
libtwolame0 0.4.0-2
|
||||||
|
libudev1 252.38-1~deb12u1
|
||||||
|
libudfread0 1.1.2-1
|
||||||
|
libunistring2 1.0-2
|
||||||
|
libuuid1 2.38.1-5+deb12u3
|
||||||
|
libv4l-0 1.22.1-5+b2
|
||||||
|
libv4lconvert0 1.22.1-5+b2
|
||||||
|
libva-drm2 2.17.0-1
|
||||||
|
libva-x11-2 2.17.0-1
|
||||||
|
libva2 2.17.0-1
|
||||||
|
libvdpau1 1.5-2
|
||||||
|
libvorbis0a 1.3.7-1
|
||||||
|
libvorbisenc2 1.3.7-1
|
||||||
|
libvorbisfile3 1.3.7-1
|
||||||
|
libvpx7 1.12.0-1+deb12u4
|
||||||
|
libwebp7 1.2.4-0.2+deb12u1
|
||||||
|
libwebpdemux2 1.2.4-0.2+deb12u1
|
||||||
|
libwebpmux3 1.2.4-0.2+deb12u1
|
||||||
|
libx11-6 2:1.8.4-2+deb12u2
|
||||||
|
libx11-data 2:1.8.4-2+deb12u2
|
||||||
|
libx11-xcb1 2:1.8.4-2+deb12u2
|
||||||
|
libx264-164 2:0.164.3095+gitbaee400-3
|
||||||
|
libx265-199 3.5-2+b1
|
||||||
|
libxau6 1:1.0.9-1
|
||||||
|
libxcb-dri3-0 1.15-1
|
||||||
|
libxcb-render0 1.15-1
|
||||||
|
libxcb-shm0 1.15-1
|
||||||
|
libxcb1 1.15-1
|
||||||
|
libxdmcp6 1:1.1.2-3
|
||||||
|
libxext6 2:1.3.4-1+b1
|
||||||
|
libxfixes3 1:6.0.0-2
|
||||||
|
libxml2 2.9.14+dfsg-1.3~deb12u2
|
||||||
|
libxrender1 1:0.9.10-1.1
|
||||||
|
libxslt1.1 1.1.35-1+deb12u1
|
||||||
|
libxt6 1:1.2.1-1.1
|
||||||
|
libxvidcore4 2:1.3.7-1
|
||||||
|
libxxhash0 0.8.1-1
|
||||||
|
libzbar0 0.23.92-7+deb12u1
|
||||||
|
libzmq5 4.3.4-6
|
||||||
|
libzstd1 1.5.4+dfsg2-5
|
||||||
|
libzvbi-common 0.2.41-1
|
||||||
|
libzvbi0 0.2.41-1
|
||||||
|
login 1:4.13+dfsg1-1+deb12u1
|
||||||
|
logsave 1.47.0-2
|
||||||
|
mariadb-client 1:10.11.11-0+deb12u1
|
||||||
|
mariadb-client-core 1:10.11.11-0+deb12u1
|
||||||
|
mariadb-common 1:10.11.11-0+deb12u1
|
||||||
|
mawk 1.3.4.20200120-3.1
|
||||||
|
media-types 10.0.0
|
||||||
|
mount 2.38.1-5+deb12u3
|
||||||
|
mysql-common 5.8+1.1.0
|
||||||
|
ncurses-base 6.4-4
|
||||||
|
ncurses-bin 6.4-4
|
||||||
|
netbase 6.4
|
||||||
|
ocl-icd-libopencl1 2.3.1-1
|
||||||
|
openssl 3.0.17-1~deb12u1
|
||||||
|
passwd 1:4.13+dfsg1-1+deb12u1
|
||||||
|
perl 5.36.0-7+deb12u2
|
||||||
|
perl-base 5.36.0-7+deb12u2
|
||||||
|
perl-modules-5.36 5.36.0-7+deb12u2
|
||||||
|
pinentry-curses 1.2.1-1
|
||||||
|
pngquant 2.17.0-1
|
||||||
|
poppler-data 0.4.12-1
|
||||||
|
poppler-utils 22.12.0-2+deb12u1
|
||||||
|
postgresql-client 15+248
|
||||||
|
postgresql-client-15 15.13-0+deb12u1
|
||||||
|
postgresql-client-common 248
|
||||||
|
qpdf 11.9.0-1
|
||||||
|
readline-common 8.2-1.3
|
||||||
|
sed 4.9-1
|
||||||
|
sensible-utils 0.0.17+nmu1
|
||||||
|
shared-mime-info 2.2-1
|
||||||
|
sysvinit-utils 3.06-4
|
||||||
|
tar 1.34+dfsg-1.2+deb12u1
|
||||||
|
tesseract-ocr 5.3.0-2
|
||||||
|
tesseract-ocr-deu 1:4.1.0-2
|
||||||
|
tesseract-ocr-eng 1:4.1.0-2
|
||||||
|
tesseract-ocr-fra 1:4.1.0-2
|
||||||
|
tesseract-ocr-ita 1:4.1.0-2
|
||||||
|
tesseract-ocr-osd 1:4.1.0-2
|
||||||
|
tesseract-ocr-spa 1:4.1.0-2
|
||||||
|
tzdata 2025b-0+deb12u1
|
||||||
|
ucf 3.0043+nmu1+deb12u1
|
||||||
|
unpaper 7.0.0-0.1
|
||||||
|
usr-is-merged 37~deb12u1
|
||||||
|
util-linux 2.38.1-5+deb12u3
|
||||||
|
util-linux-extra 2.38.1-5+deb12u3
|
||||||
|
x11-common 1:7.7+23
|
||||||
|
xfonts-encodings 1:1.0.4-2.2
|
||||||
|
xfonts-utils 1:7.7+6
|
||||||
|
zlib1g 1:1.2.13.dfsg-1
|
@@ -179,10 +179,14 @@ following:
|
|||||||
|
|
||||||
### Database Upgrades
|
### Database Upgrades
|
||||||
|
|
||||||
In general, paperless does not require a specific version of PostgreSQL or MariaDB and it is
|
Paperless-ngx is compatible with Django-supported versions of PostgreSQL and MariaDB and it is generally
|
||||||
safe to update them to newer versions. However, you should always take a backup and follow
|
safe to update them to newer versions. However, you should always take a backup and follow
|
||||||
the instructions from your database's documentation for how to upgrade between major versions.
|
the instructions from your database's documentation for how to upgrade between major versions.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
As of Paperless-ngx v2.18, the minimum supported version of PostgreSQL is 13.
|
||||||
|
|
||||||
For PostgreSQL, refer to [Upgrading a PostgreSQL Cluster](https://www.postgresql.org/docs/current/upgrading.html).
|
For PostgreSQL, refer to [Upgrading a PostgreSQL Cluster](https://www.postgresql.org/docs/current/upgrading.html).
|
||||||
|
|
||||||
For MariaDB, refer to [Upgrading MariaDB](https://mariadb.com/kb/en/upgrading/)
|
For MariaDB, refer to [Upgrading MariaDB](https://mariadb.com/kb/en/upgrading/)
|
||||||
|
@@ -1800,23 +1800,3 @@ password. All of these options come from their similarly-named [Django settings]
|
|||||||
#### [`PAPERLESS_EMAIL_USE_SSL=<bool>`](#PAPERLESS_EMAIL_USE_SSL) {#PAPERLESS_EMAIL_USE_SSL}
|
#### [`PAPERLESS_EMAIL_USE_SSL=<bool>`](#PAPERLESS_EMAIL_USE_SSL) {#PAPERLESS_EMAIL_USE_SSL}
|
||||||
|
|
||||||
: Defaults to false.
|
: Defaults to false.
|
||||||
|
|
||||||
## Remote OCR
|
|
||||||
|
|
||||||
#### [`PAPERLESS_REMOTE_OCR_ENGINE=<str>`](#PAPERLESS_REMOTE_OCR_ENGINE) {#PAPERLESS_REMOTE_OCR_ENGINE}
|
|
||||||
|
|
||||||
: The remote OCR engine to use. Currently only Azure AI is supported as "azureai".
|
|
||||||
|
|
||||||
Defaults to None, which disables remote OCR.
|
|
||||||
|
|
||||||
#### [`PAPERLESS_REMOTE_OCR_API_KEY=<str>`](#PAPERLESS_REMOTE_OCR_API_KEY) {#PAPERLESS_REMOTE_OCR_API_KEY}
|
|
||||||
|
|
||||||
: The API key to use for the remote OCR engine.
|
|
||||||
|
|
||||||
Defaults to None.
|
|
||||||
|
|
||||||
#### [`PAPERLESS_REMOTE_OCR_ENDPOINT=<str>`](#PAPERLESS_REMOTE_OCR_ENDPOINT) {#PAPERLESS_REMOTE_OCR_ENDPOINT}
|
|
||||||
|
|
||||||
: The endpoint to use for the remote OCR engine. This is required for Azure AI.
|
|
||||||
|
|
||||||
Defaults to None.
|
|
||||||
|
@@ -25,10 +25,9 @@ physical documents into a searchable online archive so you can keep, well, _less
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Organize and index** your scanned documents with tags, correspondents, types, and more.
|
- **Organize and index** your scanned documents with tags, correspondents, types, and more.
|
||||||
- _Your_ data is stored locally on _your_ server and is never transmitted or shared in any way, unless you explicitly choose to do so.
|
- _Your_ data is stored locally on _your_ server and is never transmitted or shared in any way.
|
||||||
- Performs **OCR** on your documents, adding searchable and selectable text, even to documents scanned with only images.
|
- Performs **OCR** on your documents, adding searchable and selectable text, even to documents scanned with only images.
|
||||||
- Utilizes the open-source Tesseract engine to recognize more than 100 languages.
|
- Utilizes the open-source Tesseract engine to recognize more than 100 languages.
|
||||||
- _New!_ Supports remote OCR with Azure AI (opt-in).
|
|
||||||
- Documents are saved as PDF/A format which is designed for long term storage, alongside the unaltered originals.
|
- Documents are saved as PDF/A format which is designed for long term storage, alongside the unaltered originals.
|
||||||
- Uses machine-learning to automatically add tags, correspondents and document types to your documents.
|
- Uses machine-learning to automatically add tags, correspondents and document types to your documents.
|
||||||
- Supports PDF documents, images, plain text files, Office documents (Word, Excel, PowerPoint, and LibreOffice equivalents)[^1] and more.
|
- Supports PDF documents, images, plain text files, Office documents (Word, Excel, PowerPoint, and LibreOffice equivalents)[^1] and more.
|
||||||
|
@@ -850,18 +850,6 @@ how regularly you intend to scan documents and use paperless.
|
|||||||
performed the task associated with the document, move it to the
|
performed the task associated with the document, move it to the
|
||||||
inbox.
|
inbox.
|
||||||
|
|
||||||
## Remote OCR
|
|
||||||
|
|
||||||
!!! important
|
|
||||||
|
|
||||||
This feature is disabled by default and will always remain strictly "opt-in".
|
|
||||||
|
|
||||||
Paperless-ngx supports performing OCR on documents using remote services. At the moment, this is limited to
|
|
||||||
[Microsoft's Azure "Document Intelligence" service](https://azure.microsoft.com/en-us/products/ai-services/ai-document-intelligence).
|
|
||||||
This is of course a paid service (with a free tier) which requires an Azure account and subscription. Azure AI is not affiliated with
|
|
||||||
Paperless-ngx in any way. When enabled, Paperless-ngx will automatically send appropriate documents to Azure for OCR processing, bypassing
|
|
||||||
the local OCR engine. See the [configuration](configuration.md#PAPERLESS_REMOTE_OCR_ENGINE) options for more details.
|
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
Paperless-ngx consists of the following components:
|
Paperless-ngx consists of the following components:
|
||||||
|
@@ -15,7 +15,6 @@ classifiers = [
|
|||||||
# This will allow testing to not install a webserver, mysql, etc
|
# This will allow testing to not install a webserver, mysql, etc
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azure-ai-documentintelligence>=1.0.2",
|
|
||||||
"bleach~=6.2.0",
|
"bleach~=6.2.0",
|
||||||
"celery[redis]~=5.5.1",
|
"celery[redis]~=5.5.1",
|
||||||
"channels~=4.2",
|
"channels~=4.2",
|
||||||
@@ -24,22 +23,22 @@ dependencies = [
|
|||||||
"dateparser~=1.2",
|
"dateparser~=1.2",
|
||||||
# WARNING: django does not use semver.
|
# WARNING: django does not use semver.
|
||||||
# Only patch versions are guaranteed to not introduce breaking changes.
|
# Only patch versions are guaranteed to not introduce breaking changes.
|
||||||
"django~=5.1.7",
|
"django~=5.2.5",
|
||||||
"django-allauth[socialaccount,mfa]~=65.4.0",
|
"django-allauth[socialaccount,mfa]~=65.4.0",
|
||||||
"django-auditlog~=3.1.2",
|
"django-auditlog~=3.2.1",
|
||||||
"django-cachalot~=2.8.0",
|
"django-cachalot~=2.8.0",
|
||||||
"django-celery-results~=2.6.0",
|
"django-celery-results~=2.6.0",
|
||||||
"django-compression-middleware~=0.5.0",
|
"django-compression-middleware~=0.5.0",
|
||||||
"django-cors-headers~=4.7.0",
|
"django-cors-headers~=4.7.0",
|
||||||
"django-extensions~=4.1",
|
"django-extensions~=4.1",
|
||||||
"django-filter~=25.1",
|
"django-filter~=25.1",
|
||||||
"django-guardian~=2.4.0",
|
"django-guardian~=3.0.3",
|
||||||
"django-multiselectfield~=0.1.13",
|
"django-multiselectfield~=1.0.1",
|
||||||
"django-soft-delete~=1.0.18",
|
"django-soft-delete~=1.0.18",
|
||||||
"djangorestframework~=3.15",
|
"djangorestframework~=3.15",
|
||||||
"djangorestframework-guardian~=0.3.0",
|
"djangorestframework-guardian~=0.4.0",
|
||||||
"drf-spectacular~=0.28",
|
"drf-spectacular~=0.28",
|
||||||
"drf-spectacular-sidecar~=2025.4.1",
|
"drf-spectacular-sidecar~=2025.8.1",
|
||||||
"drf-writable-nested~=0.7.1",
|
"drf-writable-nested~=0.7.1",
|
||||||
"filelock~=3.18.0",
|
"filelock~=3.18.0",
|
||||||
"flower~=2.0.1",
|
"flower~=2.0.1",
|
||||||
@@ -104,7 +103,7 @@ testing = [
|
|||||||
"imagehash",
|
"imagehash",
|
||||||
"pytest~=8.4.1",
|
"pytest~=8.4.1",
|
||||||
"pytest-cov~=6.2.1",
|
"pytest-cov~=6.2.1",
|
||||||
"pytest-django~=4.10.0",
|
"pytest-django~=4.11.1",
|
||||||
"pytest-env",
|
"pytest-env",
|
||||||
"pytest-httpx",
|
"pytest-httpx",
|
||||||
"pytest-mock",
|
"pytest-mock",
|
||||||
@@ -222,6 +221,11 @@ lint.per-file-ignores."src/paperless_tesseract/tests/test_parser.py" = [
|
|||||||
]
|
]
|
||||||
lint.isort.force-single-line = true
|
lint.isort.force-single-line = true
|
||||||
|
|
||||||
|
[tool.codespell]
|
||||||
|
write-changes = true
|
||||||
|
ignore-words-list = "criterias,afterall,valeu,ureue,equest,ure,assertIn"
|
||||||
|
skip = "src-ui/src/locale/*,src-ui/pnpm-lock.yaml,src-ui/e2e/*,src/paperless_mail/tests/samples/*,src/documents/tests/samples/*,*.po,*.json"
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
minversion = "8.0"
|
minversion = "8.0"
|
||||||
pythonpath = [
|
pythonpath = [
|
||||||
@@ -234,7 +238,6 @@ testpaths = [
|
|||||||
"src/paperless_tesseract/tests/",
|
"src/paperless_tesseract/tests/",
|
||||||
"src/paperless_tika/tests",
|
"src/paperless_tika/tests",
|
||||||
"src/paperless_text/tests/",
|
"src/paperless_text/tests/",
|
||||||
"src/paperless_remote/tests/",
|
|
||||||
]
|
]
|
||||||
addopts = [
|
addopts = [
|
||||||
"--pythonwarnings=all",
|
"--pythonwarnings=all",
|
||||||
|
@@ -125,14 +125,14 @@ class Command(MultiProcessMixin, ProgressBarMixin, BaseCommand):
|
|||||||
messages.append(
|
messages.append(
|
||||||
self.style.NOTICE(
|
self.style.NOTICE(
|
||||||
f"Document {result.doc_one_pk} fuzzy match"
|
f"Document {result.doc_one_pk} fuzzy match"
|
||||||
f" to {result.doc_two_pk} (confidence {result.ratio:.3f})",
|
f" to {result.doc_two_pk} (confidence {result.ratio:.3f})\n",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
maybe_delete_ids.append(result.doc_two_pk)
|
maybe_delete_ids.append(result.doc_two_pk)
|
||||||
|
|
||||||
if len(messages) == 0:
|
if len(messages) == 0:
|
||||||
messages.append(
|
messages.append(
|
||||||
self.style.SUCCESS("No matches found"),
|
self.style.SUCCESS("No matches found\n"),
|
||||||
)
|
)
|
||||||
self.stdout.writelines(
|
self.stdout.writelines(
|
||||||
messages,
|
messages,
|
||||||
|
@@ -2089,6 +2089,24 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def normalize_workflow_trigger_sources(trigger):
|
||||||
|
"""
|
||||||
|
Convert sources to strings to handle django-multiselectfield v1.0 changes
|
||||||
|
"""
|
||||||
|
if trigger and "sources" in trigger:
|
||||||
|
trigger["sources"] = [
|
||||||
|
str(s.value if hasattr(s, "value") else s) for s in trigger["sources"]
|
||||||
|
]
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
WorkflowTriggerSerializer.normalize_workflow_trigger_sources(validated_data)
|
||||||
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
WorkflowTriggerSerializer.normalize_workflow_trigger_sources(validated_data)
|
||||||
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
|
|
||||||
class WorkflowActionEmailSerializer(serializers.ModelSerializer):
|
class WorkflowActionEmailSerializer(serializers.ModelSerializer):
|
||||||
id = serializers.IntegerField(allow_null=True, required=False)
|
id = serializers.IntegerField(allow_null=True, required=False)
|
||||||
@@ -2253,6 +2271,8 @@ class WorkflowSerializer(serializers.ModelSerializer):
|
|||||||
if triggers is not None and triggers is not serializers.empty:
|
if triggers is not None and triggers is not serializers.empty:
|
||||||
for trigger in triggers:
|
for trigger in triggers:
|
||||||
filter_has_tags = trigger.pop("filter_has_tags", None)
|
filter_has_tags = trigger.pop("filter_has_tags", None)
|
||||||
|
# Convert sources to strings to handle django-multiselectfield v1.0 changes
|
||||||
|
WorkflowTriggerSerializer.normalize_workflow_trigger_sources(trigger)
|
||||||
trigger_instance, _ = WorkflowTrigger.objects.update_or_create(
|
trigger_instance, _ = WorkflowTrigger.objects.update_or_create(
|
||||||
id=trigger.get("id"),
|
id=trigger.get("id"),
|
||||||
defaults=trigger,
|
defaults=trigger,
|
||||||
|
@@ -123,7 +123,7 @@ class TestExportImport(
|
|||||||
|
|
||||||
self.trigger = WorkflowTrigger.objects.create(
|
self.trigger = WorkflowTrigger.objects.create(
|
||||||
type=WorkflowTrigger.WorkflowTriggerType.CONSUMPTION,
|
type=WorkflowTrigger.WorkflowTriggerType.CONSUMPTION,
|
||||||
sources=[1],
|
sources=[str(WorkflowTrigger.DocumentSourceChoices.CONSUME_FOLDER.value)],
|
||||||
filter_filename="*",
|
filter_filename="*",
|
||||||
)
|
)
|
||||||
self.action = WorkflowAction.objects.create(assign_title="new title")
|
self.action = WorkflowAction.objects.create(assign_title="new title")
|
||||||
|
@@ -87,7 +87,7 @@ class TestFuzzyMatchCommand(TestCase):
|
|||||||
filename="other_test.pdf",
|
filename="other_test.pdf",
|
||||||
)
|
)
|
||||||
stdout, _ = self.call_command()
|
stdout, _ = self.call_command()
|
||||||
self.assertEqual(stdout, "No matches found\n")
|
self.assertIn("No matches found", stdout)
|
||||||
|
|
||||||
def test_with_matches(self):
|
def test_with_matches(self):
|
||||||
"""
|
"""
|
||||||
@@ -116,7 +116,7 @@ class TestFuzzyMatchCommand(TestCase):
|
|||||||
filename="other_test.pdf",
|
filename="other_test.pdf",
|
||||||
)
|
)
|
||||||
stdout, _ = self.call_command("--processes", "1")
|
stdout, _ = self.call_command("--processes", "1")
|
||||||
self.assertRegex(stdout, self.MSG_REGEX + "\n")
|
self.assertRegex(stdout, self.MSG_REGEX)
|
||||||
|
|
||||||
def test_with_3_matches(self):
|
def test_with_3_matches(self):
|
||||||
"""
|
"""
|
||||||
@@ -152,11 +152,10 @@ class TestFuzzyMatchCommand(TestCase):
|
|||||||
filename="final_test.pdf",
|
filename="final_test.pdf",
|
||||||
)
|
)
|
||||||
stdout, _ = self.call_command()
|
stdout, _ = self.call_command()
|
||||||
lines = [x.strip() for x in stdout.split("\n") if len(x.strip())]
|
lines = [x.strip() for x in stdout.splitlines() if x.strip()]
|
||||||
self.assertEqual(len(lines), 3)
|
self.assertEqual(len(lines), 3)
|
||||||
self.assertRegex(lines[0], self.MSG_REGEX)
|
for line in lines:
|
||||||
self.assertRegex(lines[1], self.MSG_REGEX)
|
self.assertRegex(line, self.MSG_REGEX)
|
||||||
self.assertRegex(lines[2], self.MSG_REGEX)
|
|
||||||
|
|
||||||
def test_document_deletion(self):
|
def test_document_deletion(self):
|
||||||
"""
|
"""
|
||||||
@@ -197,14 +196,12 @@ class TestFuzzyMatchCommand(TestCase):
|
|||||||
|
|
||||||
stdout, _ = self.call_command("--delete")
|
stdout, _ = self.call_command("--delete")
|
||||||
|
|
||||||
lines = [x.strip() for x in stdout.split("\n") if len(x.strip())]
|
self.assertIn(
|
||||||
self.assertEqual(len(lines), 3)
|
|
||||||
self.assertEqual(
|
|
||||||
lines[0],
|
|
||||||
"The command is configured to delete documents. Use with caution",
|
"The command is configured to delete documents. Use with caution",
|
||||||
|
stdout,
|
||||||
)
|
)
|
||||||
self.assertRegex(lines[1], self.MSG_REGEX)
|
self.assertRegex(stdout, self.MSG_REGEX)
|
||||||
self.assertEqual(lines[2], "Deleting 1 documents based on ratio matches")
|
self.assertIn("Deleting 1 documents based on ratio matches", stdout)
|
||||||
|
|
||||||
self.assertEqual(Document.objects.count(), 2)
|
self.assertEqual(Document.objects.count(), 2)
|
||||||
self.assertIsNotNone(Document.objects.get(pk=1))
|
self.assertIsNotNone(Document.objects.get(pk=1))
|
||||||
|
@@ -104,7 +104,7 @@ class TestReverseMigrateWorkflow(TestMigrations):
|
|||||||
|
|
||||||
trigger = WorkflowTrigger.objects.create(
|
trigger = WorkflowTrigger.objects.create(
|
||||||
type=0,
|
type=0,
|
||||||
sources=[DocumentSource.ConsumeFolder],
|
sources=[str(DocumentSource.ConsumeFolder)],
|
||||||
filter_path="*/path/*",
|
filter_path="*/path/*",
|
||||||
filter_filename="*file*",
|
filter_filename="*file*",
|
||||||
)
|
)
|
||||||
|
@@ -54,7 +54,7 @@ class HttpRemoteUserMiddleware(PersistentRemoteUserMiddleware):
|
|||||||
|
|
||||||
header = settings.HTTP_REMOTE_USER_HEADER_NAME
|
header = settings.HTTP_REMOTE_USER_HEADER_NAME
|
||||||
|
|
||||||
def process_request(self, request: HttpRequest) -> None:
|
def __call__(self, request: HttpRequest) -> None:
|
||||||
# If remote user auth is enabled only for the frontend, not the API,
|
# If remote user auth is enabled only for the frontend, not the API,
|
||||||
# then we need dont want to authenticate the user for API requests.
|
# then we need dont want to authenticate the user for API requests.
|
||||||
if (
|
if (
|
||||||
@@ -62,8 +62,8 @@ class HttpRemoteUserMiddleware(PersistentRemoteUserMiddleware):
|
|||||||
and "paperless.auth.PaperlessRemoteUserAuthentication"
|
and "paperless.auth.PaperlessRemoteUserAuthentication"
|
||||||
not in settings.REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"]
|
not in settings.REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"]
|
||||||
):
|
):
|
||||||
return
|
return self.get_response(request)
|
||||||
return super().process_request(request)
|
return super().__call__(request)
|
||||||
|
|
||||||
|
|
||||||
class PaperlessRemoteUserAuthentication(authentication.RemoteUserAuthentication):
|
class PaperlessRemoteUserAuthentication(authentication.RemoteUserAuthentication):
|
||||||
|
@@ -214,31 +214,3 @@ def audit_log_check(app_configs, **kwargs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@register()
|
|
||||||
def check_postgres_version(app_configs, **kwargs):
|
|
||||||
"""
|
|
||||||
Django 5.2 removed PostgreSQL 13 support and thus it will be removed in
|
|
||||||
a future Paperless-ngx version. This check can be removed eventually.
|
|
||||||
See https://docs.djangoproject.com/en/5.2/releases/5.2/#dropped-support-for-postgresql-13
|
|
||||||
"""
|
|
||||||
db_conn = connections["default"]
|
|
||||||
result = []
|
|
||||||
if db_conn.vendor == "postgresql":
|
|
||||||
try:
|
|
||||||
with db_conn.cursor() as cursor:
|
|
||||||
cursor.execute("SHOW server_version;")
|
|
||||||
version = cursor.fetchone()[0]
|
|
||||||
if version.startswith("13"):
|
|
||||||
return [
|
|
||||||
Warning(
|
|
||||||
"PostgreSQL 13 is deprecated and will not be supported in a future Paperless-ngx release.",
|
|
||||||
hint="Upgrade to PostgreSQL 14 or newer.",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
except Exception: # pragma: no cover
|
|
||||||
# Don't block checks on version query failure
|
|
||||||
pass
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
@@ -324,7 +324,6 @@ INSTALLED_APPS = [
|
|||||||
"paperless_tesseract.apps.PaperlessTesseractConfig",
|
"paperless_tesseract.apps.PaperlessTesseractConfig",
|
||||||
"paperless_text.apps.PaperlessTextConfig",
|
"paperless_text.apps.PaperlessTextConfig",
|
||||||
"paperless_mail.apps.PaperlessMailConfig",
|
"paperless_mail.apps.PaperlessMailConfig",
|
||||||
"paperless_remote.apps.PaperlessRemoteParserConfig",
|
|
||||||
"django.contrib.admin",
|
"django.contrib.admin",
|
||||||
"rest_framework",
|
"rest_framework",
|
||||||
"rest_framework.authtoken",
|
"rest_framework.authtoken",
|
||||||
@@ -1444,10 +1443,3 @@ WEBHOOKS_ALLOW_INTERNAL_REQUESTS = __get_boolean(
|
|||||||
"PAPERLESS_WEBHOOKS_ALLOW_INTERNAL_REQUESTS",
|
"PAPERLESS_WEBHOOKS_ALLOW_INTERNAL_REQUESTS",
|
||||||
"true",
|
"true",
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Remote Parser #
|
|
||||||
###############################################################################
|
|
||||||
REMOTE_OCR_ENGINE = os.getenv("PAPERLESS_REMOTE_OCR_ENGINE")
|
|
||||||
REMOTE_OCR_API_KEY = os.getenv("PAPERLESS_REMOTE_OCR_API_KEY")
|
|
||||||
REMOTE_OCR_ENDPOINT = os.getenv("PAPERLESS_REMOTE_OCR_ENDPOINT")
|
|
||||||
|
@@ -9,7 +9,6 @@ from documents.tests.utils import DirectoriesMixin
|
|||||||
from documents.tests.utils import FileSystemAssertsMixin
|
from documents.tests.utils import FileSystemAssertsMixin
|
||||||
from paperless.checks import audit_log_check
|
from paperless.checks import audit_log_check
|
||||||
from paperless.checks import binaries_check
|
from paperless.checks import binaries_check
|
||||||
from paperless.checks import check_postgres_version
|
|
||||||
from paperless.checks import debug_mode_check
|
from paperless.checks import debug_mode_check
|
||||||
from paperless.checks import paths_check
|
from paperless.checks import paths_check
|
||||||
from paperless.checks import settings_values_check
|
from paperless.checks import settings_values_check
|
||||||
@@ -263,39 +262,3 @@ class TestAuditLogChecks(TestCase):
|
|||||||
("auditlog table was found but audit log is disabled."),
|
("auditlog table was found but audit log is disabled."),
|
||||||
msg.msg,
|
msg.msg,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestPostgresVersionCheck(TestCase):
|
|
||||||
@mock.patch("paperless.checks.connections")
|
|
||||||
def test_postgres_13_warns(self, mock_connections):
|
|
||||||
mock_connection = mock.MagicMock()
|
|
||||||
mock_connection.vendor = "postgresql"
|
|
||||||
mock_cursor = mock.MagicMock()
|
|
||||||
mock_cursor.__enter__.return_value.fetchone.return_value = ["13.11"]
|
|
||||||
mock_connection.cursor.return_value = mock_cursor
|
|
||||||
mock_connections.__getitem__.return_value = mock_connection
|
|
||||||
|
|
||||||
warnings = check_postgres_version(None)
|
|
||||||
self.assertEqual(len(warnings), 1)
|
|
||||||
self.assertIn("PostgreSQL 13 is deprecated", warnings[0].msg)
|
|
||||||
|
|
||||||
@mock.patch("paperless.checks.connections")
|
|
||||||
def test_postgres_14_passes(self, mock_connections):
|
|
||||||
mock_connection = mock.MagicMock()
|
|
||||||
mock_connection.vendor = "postgresql"
|
|
||||||
mock_cursor = mock.MagicMock()
|
|
||||||
mock_cursor.__enter__.return_value.fetchone.return_value = ["14.10"]
|
|
||||||
mock_connection.cursor.return_value = mock_cursor
|
|
||||||
mock_connections.__getitem__.return_value = mock_connection
|
|
||||||
|
|
||||||
warnings = check_postgres_version(None)
|
|
||||||
self.assertEqual(warnings, [])
|
|
||||||
|
|
||||||
@mock.patch("paperless.checks.connections")
|
|
||||||
def test_non_postgres_skipped(self, mock_connections):
|
|
||||||
mock_connection = mock.MagicMock()
|
|
||||||
mock_connection.vendor = "sqlite"
|
|
||||||
mock_connections.__getitem__.return_value = mock_connection
|
|
||||||
|
|
||||||
warnings = check_postgres_version(None)
|
|
||||||
self.assertEqual(warnings, [])
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
@@ -91,6 +92,7 @@ class TestRemoteUser(DirectoriesMixin, APITestCase):
|
|||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
REST_FRAMEWORK={
|
REST_FRAMEWORK={
|
||||||
|
**settings.REST_FRAMEWORK,
|
||||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||||
"rest_framework.authentication.BasicAuthentication",
|
"rest_framework.authentication.BasicAuthentication",
|
||||||
"rest_framework.authentication.TokenAuthentication",
|
"rest_framework.authentication.TokenAuthentication",
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
# this is here so that django finds the checks.
|
|
||||||
from paperless_remote.checks import check_remote_parser_configured
|
|
||||||
|
|
||||||
__all__ = ["check_remote_parser_configured"]
|
|
@@ -1,14 +0,0 @@
|
|||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
from paperless_remote.signals import remote_consumer_declaration
|
|
||||||
|
|
||||||
|
|
||||||
class PaperlessRemoteParserConfig(AppConfig):
|
|
||||||
name = "paperless_remote"
|
|
||||||
|
|
||||||
def ready(self):
|
|
||||||
from documents.signals import document_consumer_declaration
|
|
||||||
|
|
||||||
document_consumer_declaration.connect(remote_consumer_declaration)
|
|
||||||
|
|
||||||
AppConfig.ready(self)
|
|
@@ -1,15 +0,0 @@
|
|||||||
from django.conf import settings
|
|
||||||
from django.core.checks import Error
|
|
||||||
from django.core.checks import register
|
|
||||||
|
|
||||||
|
|
||||||
@register()
|
|
||||||
def check_remote_parser_configured(app_configs, **kwargs):
|
|
||||||
if settings.REMOTE_OCR_ENGINE == "azureai" and not settings.REMOTE_OCR_ENDPOINT:
|
|
||||||
return [
|
|
||||||
Error(
|
|
||||||
"Azure AI remote parser requires endpoint to be configured.",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
return []
|
|
@@ -1,113 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
from paperless_tesseract.parsers import RasterisedDocumentParser
|
|
||||||
|
|
||||||
|
|
||||||
class RemoteEngineConfig:
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
engine: str,
|
|
||||||
api_key: str | None = None,
|
|
||||||
endpoint: str | None = None,
|
|
||||||
):
|
|
||||||
self.engine = engine
|
|
||||||
self.api_key = api_key
|
|
||||||
self.endpoint = endpoint
|
|
||||||
|
|
||||||
def engine_is_valid(self):
|
|
||||||
valid = self.engine in ["azureai"] and self.api_key is not None
|
|
||||||
if self.engine == "azureai":
|
|
||||||
valid = valid and self.endpoint is not None
|
|
||||||
return valid
|
|
||||||
|
|
||||||
|
|
||||||
class RemoteDocumentParser(RasterisedDocumentParser):
|
|
||||||
"""
|
|
||||||
This parser uses a remote OCR engine to parse documents. Currently, it supports Azure AI Vision
|
|
||||||
as this is the only service that provides a remote OCR API with text-embedded PDF output.
|
|
||||||
"""
|
|
||||||
|
|
||||||
logging_name = "paperless.parsing.remote"
|
|
||||||
|
|
||||||
def get_settings(self) -> RemoteEngineConfig:
|
|
||||||
"""
|
|
||||||
Returns the configuration for the remote OCR engine, loaded from Django settings.
|
|
||||||
"""
|
|
||||||
return RemoteEngineConfig(
|
|
||||||
engine=settings.REMOTE_OCR_ENGINE,
|
|
||||||
api_key=settings.REMOTE_OCR_API_KEY,
|
|
||||||
endpoint=settings.REMOTE_OCR_ENDPOINT,
|
|
||||||
)
|
|
||||||
|
|
||||||
def supported_mime_types(self):
|
|
||||||
if self.settings.engine_is_valid():
|
|
||||||
return {
|
|
||||||
"application/pdf": ".pdf",
|
|
||||||
"image/png": ".png",
|
|
||||||
"image/jpeg": ".jpg",
|
|
||||||
"image/tiff": ".tiff",
|
|
||||||
"image/bmp": ".bmp",
|
|
||||||
"image/gif": ".gif",
|
|
||||||
"image/webp": ".webp",
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def azure_ai_vision_parse(
|
|
||||||
self,
|
|
||||||
file: Path,
|
|
||||||
) -> str | None:
|
|
||||||
"""
|
|
||||||
Uses Azure AI Vision to parse the document and return the text content.
|
|
||||||
It requests a searchable PDF output with embedded text.
|
|
||||||
The PDF is saved to the archive_path attribute.
|
|
||||||
Returns the text content extracted from the document.
|
|
||||||
If the parsing fails, it returns None.
|
|
||||||
"""
|
|
||||||
from azure.ai.documentintelligence import DocumentIntelligenceClient
|
|
||||||
from azure.ai.documentintelligence.models import AnalyzeDocumentRequest
|
|
||||||
from azure.ai.documentintelligence.models import AnalyzeOutputOption
|
|
||||||
from azure.ai.documentintelligence.models import DocumentContentFormat
|
|
||||||
from azure.core.credentials import AzureKeyCredential
|
|
||||||
|
|
||||||
client = DocumentIntelligenceClient(
|
|
||||||
endpoint=self.settings.endpoint,
|
|
||||||
credential=AzureKeyCredential(self.settings.api_key),
|
|
||||||
)
|
|
||||||
|
|
||||||
with file.open("rb") as f:
|
|
||||||
analyze_request = AnalyzeDocumentRequest(bytes_source=f.read())
|
|
||||||
poller = client.begin_analyze_document(
|
|
||||||
model_id="prebuilt-read",
|
|
||||||
body=analyze_request,
|
|
||||||
output_content_format=DocumentContentFormat.TEXT,
|
|
||||||
output=[AnalyzeOutputOption.PDF], # request searchable PDF output
|
|
||||||
content_type="application/json",
|
|
||||||
)
|
|
||||||
|
|
||||||
poller.wait()
|
|
||||||
result_id = poller.details["operation_id"]
|
|
||||||
result = poller.result()
|
|
||||||
|
|
||||||
# Download the PDF with embedded text
|
|
||||||
self.archive_path = Path(self.tempdir) / "archive.pdf"
|
|
||||||
with self.archive_path.open("wb") as f:
|
|
||||||
for chunk in client.get_analyze_result_pdf(
|
|
||||||
model_id="prebuilt-read",
|
|
||||||
result_id=result_id,
|
|
||||||
):
|
|
||||||
f.write(chunk)
|
|
||||||
|
|
||||||
return result.content
|
|
||||||
|
|
||||||
def parse(self, document_path: Path, mime_type, file_name=None):
|
|
||||||
if not self.settings.engine_is_valid():
|
|
||||||
self.log.warning(
|
|
||||||
"No valid remote parser engine is configured, content will be empty.",
|
|
||||||
)
|
|
||||||
self.text = ""
|
|
||||||
return
|
|
||||||
elif self.settings.engine == "azureai":
|
|
||||||
self.text = self.azure_ai_vision_parse(document_path)
|
|
@@ -1,18 +0,0 @@
|
|||||||
def get_parser(*args, **kwargs):
|
|
||||||
from paperless_remote.parsers import RemoteDocumentParser
|
|
||||||
|
|
||||||
return RemoteDocumentParser(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def get_supported_mime_types():
|
|
||||||
from paperless_remote.parsers import RemoteDocumentParser
|
|
||||||
|
|
||||||
return RemoteDocumentParser(None).supported_mime_types()
|
|
||||||
|
|
||||||
|
|
||||||
def remote_consumer_declaration(sender, **kwargs):
|
|
||||||
return {
|
|
||||||
"parser": get_parser,
|
|
||||||
"weight": 5,
|
|
||||||
"mime_types": get_supported_mime_types(),
|
|
||||||
}
|
|
Binary file not shown.
@@ -1,29 +0,0 @@
|
|||||||
from django.test import TestCase
|
|
||||||
from django.test import override_settings
|
|
||||||
|
|
||||||
from paperless_remote import check_remote_parser_configured
|
|
||||||
|
|
||||||
|
|
||||||
class TestChecks(TestCase):
|
|
||||||
@override_settings(REMOTE_OCR_ENGINE=None)
|
|
||||||
def test_no_engine(self):
|
|
||||||
msgs = check_remote_parser_configured(None)
|
|
||||||
self.assertEqual(len(msgs), 0)
|
|
||||||
|
|
||||||
@override_settings(REMOTE_OCR_ENGINE="azureai")
|
|
||||||
@override_settings(REMOTE_OCR_API_KEY="somekey")
|
|
||||||
@override_settings(REMOTE_OCR_ENDPOINT=None)
|
|
||||||
def test_azure_no_endpoint(self):
|
|
||||||
msgs = check_remote_parser_configured(None)
|
|
||||||
self.assertEqual(len(msgs), 1)
|
|
||||||
self.assertTrue(
|
|
||||||
msgs[0].msg.startswith(
|
|
||||||
"Azure AI remote parser requires endpoint to be configured.",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
@override_settings(REMOTE_OCR_ENGINE="something")
|
|
||||||
@override_settings(REMOTE_OCR_API_KEY="somekey")
|
|
||||||
def test_valid_configuration(self):
|
|
||||||
msgs = check_remote_parser_configured(None)
|
|
||||||
self.assertEqual(len(msgs), 0)
|
|
@@ -1,101 +0,0 @@
|
|||||||
import uuid
|
|
||||||
from pathlib import Path
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
from django.test import override_settings
|
|
||||||
|
|
||||||
from documents.tests.utils import DirectoriesMixin
|
|
||||||
from documents.tests.utils import FileSystemAssertsMixin
|
|
||||||
from paperless_remote.parsers import RemoteDocumentParser
|
|
||||||
from paperless_remote.signals import get_parser
|
|
||||||
|
|
||||||
|
|
||||||
class TestParser(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
|
||||||
SAMPLE_FILES = Path(__file__).resolve().parent / "samples"
|
|
||||||
|
|
||||||
def assertContainsStrings(self, content, strings):
|
|
||||||
# Asserts that all strings appear in content, in the given order.
|
|
||||||
indices = []
|
|
||||||
for s in strings:
|
|
||||||
if s in content:
|
|
||||||
indices.append(content.index(s))
|
|
||||||
else:
|
|
||||||
self.fail(f"'{s}' is not in '{content}'")
|
|
||||||
self.assertListEqual(indices, sorted(indices))
|
|
||||||
|
|
||||||
@mock.patch("paperless_tesseract.parsers.run_subprocess")
|
|
||||||
@mock.patch("azure.ai.documentintelligence.DocumentIntelligenceClient")
|
|
||||||
def test_get_text_with_azure(self, mock_client_cls, mock_subprocess):
|
|
||||||
# Arrange mock Azure client
|
|
||||||
mock_client = mock.Mock()
|
|
||||||
mock_client_cls.return_value = mock_client
|
|
||||||
|
|
||||||
# Simulate poller result and its `.details`
|
|
||||||
mock_poller = mock.Mock()
|
|
||||||
mock_poller.wait.return_value = None
|
|
||||||
mock_poller.details = {"operation_id": "fake-op-id"}
|
|
||||||
mock_client.begin_analyze_document.return_value = mock_poller
|
|
||||||
mock_poller.result.return_value.content = "This is a test document."
|
|
||||||
|
|
||||||
# Return dummy PDF bytes
|
|
||||||
mock_client.get_analyze_result_pdf.return_value = [
|
|
||||||
b"%PDF-",
|
|
||||||
b"1.7 ",
|
|
||||||
b"FAKEPDF",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Simulate pdftotext by writing dummy text to sidecar file
|
|
||||||
def fake_run(cmd, *args, **kwargs):
|
|
||||||
with Path(cmd[-1]).open("w", encoding="utf-8") as f:
|
|
||||||
f.write("This is a test document.")
|
|
||||||
|
|
||||||
mock_subprocess.side_effect = fake_run
|
|
||||||
|
|
||||||
with override_settings(
|
|
||||||
REMOTE_OCR_ENGINE="azureai",
|
|
||||||
REMOTE_OCR_API_KEY="somekey",
|
|
||||||
REMOTE_OCR_ENDPOINT="https://endpoint.cognitiveservices.azure.com",
|
|
||||||
):
|
|
||||||
parser = get_parser(uuid.uuid4())
|
|
||||||
parser.parse(
|
|
||||||
self.SAMPLE_FILES / "simple-digital.pdf",
|
|
||||||
"application/pdf",
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertContainsStrings(
|
|
||||||
parser.text.strip(),
|
|
||||||
["This is a test document."],
|
|
||||||
)
|
|
||||||
|
|
||||||
@override_settings(
|
|
||||||
REMOTE_OCR_ENGINE="azureai",
|
|
||||||
REMOTE_OCR_API_KEY="key",
|
|
||||||
REMOTE_OCR_ENDPOINT="https://endpoint.cognitiveservices.azure.com",
|
|
||||||
)
|
|
||||||
def test_supported_mime_types_valid_config(self):
|
|
||||||
parser = RemoteDocumentParser(uuid.uuid4())
|
|
||||||
expected_types = {
|
|
||||||
"application/pdf": ".pdf",
|
|
||||||
"image/png": ".png",
|
|
||||||
"image/jpeg": ".jpg",
|
|
||||||
"image/tiff": ".tiff",
|
|
||||||
"image/bmp": ".bmp",
|
|
||||||
"image/gif": ".gif",
|
|
||||||
"image/webp": ".webp",
|
|
||||||
}
|
|
||||||
self.assertEqual(parser.supported_mime_types(), expected_types)
|
|
||||||
|
|
||||||
def test_supported_mime_types_invalid_config(self):
|
|
||||||
parser = get_parser(uuid.uuid4())
|
|
||||||
self.assertEqual(parser.supported_mime_types(), {})
|
|
||||||
|
|
||||||
@override_settings(
|
|
||||||
REMOTE_OCR_ENGINE=None,
|
|
||||||
REMOTE_OCR_API_KEY=None,
|
|
||||||
REMOTE_OCR_ENDPOINT=None,
|
|
||||||
)
|
|
||||||
def test_parse_with_invalid_config(self):
|
|
||||||
parser = get_parser(uuid.uuid4())
|
|
||||||
parser.parse(self.SAMPLE_FILES / "simple-digital.pdf", "application/pdf")
|
|
||||||
self.assertEqual(parser.text, "")
|
|
109
uv.lock
generated
109
uv.lock
generated
@@ -93,34 +93,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/af/cc/55a32a2c98022d88812b5986d2a92c4ff3ee087e83b712ebc703bba452bf/Automat-24.8.1-py3-none-any.whl", hash = "sha256:bf029a7bc3da1e2c24da2343e7598affaa9f10bf0ab63ff808566ce90551e02a", size = 42585, upload-time = "2024-08-19T17:31:56.729Z" },
|
{ url = "https://files.pythonhosted.org/packages/af/cc/55a32a2c98022d88812b5986d2a92c4ff3ee087e83b712ebc703bba452bf/Automat-24.8.1-py3-none-any.whl", hash = "sha256:bf029a7bc3da1e2c24da2343e7598affaa9f10bf0ab63ff808566ce90551e02a", size = 42585, upload-time = "2024-08-19T17:31:56.729Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "azure-ai-documentintelligence"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "azure-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
{ name = "isodate", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
{ name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/44/7b/8115cd713e2caa5e44def85f2b7ebd02a74ae74d7113ba20bdd41fd6dd80/azure_ai_documentintelligence-1.0.2.tar.gz", hash = "sha256:4d75a2513f2839365ebabc0e0e1772f5601b3a8c9a71e75da12440da13b63484", size = 170940 }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d9/75/c9ec040f23082f54ffb1977ff8f364c2d21c79a640a13d1c1809e7fd6b1a/azure_ai_documentintelligence-1.0.2-py3-none-any.whl", hash = "sha256:e1fb446abbdeccc9759d897898a0fe13141ed29f9ad11fc705f951925822ed59", size = 106005 },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "azure-core"
|
|
||||||
version = "1.33.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
{ name = "six", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
{ name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/75/aa/7c9db8edd626f1a7d99d09ef7926f6f4fb34d5f9fa00dc394afdfe8e2a80/azure_core-1.33.0.tar.gz", hash = "sha256:f367aa07b5e3005fec2c1e184b882b0b039910733907d001c20fb08ebb8c0eb9", size = 295633 }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/07/b7/76b7e144aa53bd206bf1ce34fa75350472c3f69bf30e5c8c18bc9881035d/azure_core-1.33.0-py3-none-any.whl", hash = "sha256:9b5b6d0223a1d38c37500e6971118c1e0f13f54951e6893968b38910bc9cda8f", size = 207071 },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "babel"
|
name = "babel"
|
||||||
version = "2.17.0"
|
version = "2.17.0"
|
||||||
@@ -654,15 +626,15 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django"
|
name = "django"
|
||||||
version = "5.1.8"
|
version = "5.2.5"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "asgiref", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "asgiref", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "sqlparse", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "sqlparse", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/00/40/45adc1b93435d1b418654a734b68351bb6ce0a0e5e37b2f0e9aeb1a2e233/Django-5.1.8.tar.gz", hash = "sha256:42e92a1dd2810072bcc40a39a212b693f94406d0ba0749e68eb642f31dc770b4", size = 10723602, upload-time = "2025-04-02T11:19:56.028Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/62/9b/779f853c3d2d58b9e08346061ff3e331cdec3fe3f53aae509e256412a593/django-5.2.5.tar.gz", hash = "sha256:0745b25681b129a77aae3d4f6549b62d3913d74407831abaa0d9021a03954bae", size = 10859748, upload-time = "2025-08-06T08:26:29.978Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/0d/e6dd0ed898b920fec35c6eeeb9acbeb831fff19ad21c5e684744df1d4a36/Django-5.1.8-py3-none-any.whl", hash = "sha256:11b28fa4b00e59d0def004e9ee012fefbb1065a5beb39ee838983fd24493ad4f", size = 8277130, upload-time = "2025-04-02T11:19:51.591Z" },
|
{ url = "https://files.pythonhosted.org/packages/9d/6e/98a1d23648e0085bb5825326af17612ecd8fc76be0ce96ea4dc35e17b926/django-5.2.5-py3-none-any.whl", hash = "sha256:2b2ada0ee8a5ff743a40e2b9820d1f8e24c11bac9ae6469cd548f0057ea6ddcd", size = 8302999, upload-time = "2025-08-06T08:26:23.562Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -688,15 +660,15 @@ socialaccount = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-auditlog"
|
name = "django-auditlog"
|
||||||
version = "3.1.2"
|
version = "3.2.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/0e/3a/61bfb180019d08db3f7a2e4097bda14ee32bd57f5dffda0c84b2d4c26304/django_auditlog-3.1.2.tar.gz", hash = "sha256:435345b4055d16abfb4ada4bf11320f9e2f6d343874464471fa0041f13f3a474", size = 69359, upload-time = "2025-04-26T11:01:56.553Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/e1/46/9da1d94493832fa18d2f6324a76d387fa232001593866987a96047709f4e/django_auditlog-3.2.1.tar.gz", hash = "sha256:63a4c9f7793e94eed804bc31a04d9b0b58244b1d280e2ed273c8b406bff1f779", size = 72926, upload-time = "2025-07-03T20:08:17.734Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/af/34/47edd758abcb4426953b5ff2fa4dd9956c2304e96160ab1b95c3a1ab6e61/django_auditlog-3.1.2-py3-none-any.whl", hash = "sha256:6432a83fdf4397a726488d101fedcb62daafd6d4b825a0fc4c50e3657f5883cd", size = 37312, upload-time = "2025-04-26T11:01:16.776Z" },
|
{ url = "https://files.pythonhosted.org/packages/a7/06/67296d050a72dcd76f57f220df621cb27e5b9282ba7ad0f5f74870dce241/django_auditlog-3.2.1-py3-none-any.whl", hash = "sha256:99603ca9d015f7e9b062b1c34f3e0826a3ce6ae6e5950c81bb7e663f7802a899", size = 38330, upload-time = "2025-07-03T20:07:51.735Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -792,38 +764,38 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-guardian"
|
name = "django-guardian"
|
||||||
version = "2.4.0"
|
version = "3.0.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/6f/4c/d1f6923a0ad7f16c403a54c09e94acb76ac6c3765e02523fb09b2b03e1a8/django-guardian-2.4.0.tar.gz", hash = "sha256:c58a68ae76922d33e6bdc0e69af1892097838de56e93e78a8361090bcd9f89a0", size = 159008, upload-time = "2021-05-23T22:11:26.23Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/30/c2/3ed43813dd7313f729dbaa829b4f9ed4a647530151f672cfb5f843c12edf/django_guardian-3.0.3.tar.gz", hash = "sha256:4e59eab4d836da5a027cf0c176d14bc2a4e22cbbdf753159a03946c08c8a196d", size = 85410, upload-time = "2025-06-25T20:42:17.475Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/a2/25/869df12e544b51f583254aadbba6c1a95e11d2d08edeb9e58dd715112db5/django_guardian-2.4.0-py3-none-any.whl", hash = "sha256:440ca61358427e575323648b25f8384739e54c38b3d655c81d75e0cd0d61b697", size = 106107, upload-time = "2021-05-23T22:11:22.75Z" },
|
{ url = "https://files.pythonhosted.org/packages/8b/13/e6f629a978ef5fab8b8d2760cacc3e451016cef952cf4c049d672c5c6b07/django_guardian-3.0.3-py3-none-any.whl", hash = "sha256:d2164cea9f03c369d7ade21802710f3ab23ca6734bcc7dfcfb385906783916c7", size = 118198, upload-time = "2025-06-25T20:42:15.377Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-multiselectfield"
|
name = "django-multiselectfield"
|
||||||
version = "0.1.13"
|
version = "1.0.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/dd/c3/1a326cc669fea63f22e63f6e2b2b014534a15966506e8d7fa3c232aced42/django_multiselectfield-0.1.13.tar.gz", hash = "sha256:437d72632f4c0ca416951917632529c3d1d42b62bb6c3c03e3396fa50265be94", size = 11704, upload-time = "2024-07-01T05:40:39.456Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/04/9a/27060e8aa491ff2d286054df2e89df481a8dfe0e5e459fa36c0f48e3c10c/django_multiselectfield-1.0.1.tar.gz", hash = "sha256:3f8b4fff3e07d4a91c8bb4b809bc35caeb22b41769b606f4c9edc53b8d72a667", size = 22025, upload-time = "2025-06-12T14:41:21.599Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/be/9e/3ed6f072f1e806516dbc8c95e4ecae7b87af6757eb5d428857ea0a097e76/django_multiselectfield-0.1.13-py3-none-any.whl", hash = "sha256:f146ef568c823a409f4021b98781666ec2debabfceca9176116d749dc39cb8b3", size = 14804, upload-time = "2024-07-01T05:40:37.549Z" },
|
{ url = "https://files.pythonhosted.org/packages/6d/10/23c0644cf67567bbe4e3a2eeeec0e9c79b701990c0e07c5ee4a4f8897f91/django_multiselectfield-1.0.1-py3-none-any.whl", hash = "sha256:18dc14801f7eca844a48e21cba6d8ec35b9b581f2373bbb2cb75e6994518259a", size = 20481, upload-time = "2025-06-12T14:41:20.107Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-soft-delete"
|
name = "django-soft-delete"
|
||||||
version = "1.0.18"
|
version = "1.0.19"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ec/7e/89cba723dd5d34ccb6003f4812de7f5c69ba32bd73ab37f2bb21ff344c6c/django_soft_delete-1.0.18.tar.gz", hash = "sha256:d2f9db449a4f008e9786f82fa4bafbe4075f7a0b3284844735007e988b2a4df6", size = 11979, upload-time = "2025-02-01T13:43:53.804Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/ce/77/44a6615a7da3ca0ddc624039d399d17d6c3503e1c2dad08b443f8d4a3570/django_soft_delete-1.0.19.tar.gz", hash = "sha256:c67ee8920e1456eca84cc59b3304ef27fa9d476b516be726ce7e1fc558502908", size = 11993, upload-time = "2025-06-19T20:32:20.373Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/f7/d0/6dcca209e48081213854088fc7014e9dbdcd24f4ec2118f8ee29d11c8623/django_soft_delete-1.0.18-py3-none-any.whl", hash = "sha256:603a29e82bbb7a5bada69f2754fad225ccd8cd7f485320ec06d0fc4e9dfddcf0", size = 10876, upload-time = "2025-02-01T13:43:52.109Z" },
|
{ url = "https://files.pythonhosted.org/packages/96/9e/f8b5a02cdcba606eb40fbe30fe0c9c7493a2c18f83ec3b4620e4e86a34d3/django_soft_delete-1.0.19-py3-none-any.whl", hash = "sha256:46aa5fab513db566d3d7a832529ed27245b5900eaaa705535bc7674055801a46", size = 10889, upload-time = "2025-06-19T20:32:19.083Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -863,28 +835,28 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "djangorestframework"
|
name = "djangorestframework"
|
||||||
version = "3.16.0"
|
version = "3.16.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/7d/97/112c5a72e6917949b6d8a18ad6c6e72c46da4290c8f36ee5f1c1dcbc9901/djangorestframework-3.16.0.tar.gz", hash = "sha256:f022ff46613584de994c0c6a4aebbace5fd700555fbe9d33b865ebf173eba6c9", size = 1068408, upload-time = "2025-03-28T14:18:42.065Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/8a/95/5376fe618646fde6899b3cdc85fd959716bb67542e273a76a80d9f326f27/djangorestframework-3.16.1.tar.gz", hash = "sha256:166809528b1aced0a17dc66c24492af18049f2c9420dbd0be29422029cfc3ff7", size = 1089735, upload-time = "2025-08-06T17:50:53.251Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/eb/3e/2448e93f4f87fc9a9f35e73e3c05669e0edd0c2526834686e949bb1fd303/djangorestframework-3.16.0-py3-none-any.whl", hash = "sha256:bea7e9f6b96a8584c5224bfb2e4348dfb3f8b5e34edbecb98da258e892089361", size = 1067305, upload-time = "2025-03-28T14:18:39.489Z" },
|
{ url = "https://files.pythonhosted.org/packages/b0/ce/bf8b9d3f415be4ac5588545b5fcdbbb841977db1c1d923f7568eeabe1689/djangorestframework-3.16.1-py3-none-any.whl", hash = "sha256:33a59f47fb9c85ede792cbf88bde71893bcda0667bc573f784649521f1102cec", size = 1080442, upload-time = "2025-08-06T17:50:50.667Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "djangorestframework-guardian"
|
name = "djangorestframework-guardian"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "django-guardian", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django-guardian", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "djangorestframework", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "djangorestframework", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/e5/80/0f2190bacfe7c7b2e22d0e1e695882ec3123f9e58817c8392a258cd46442/djangorestframework-guardian-0.3.0.tar.gz", hash = "sha256:1883756452d9bfcc2a51fb4e039a6837a8f6697c756447aa83af085749b59330", size = 8647, upload-time = "2019-10-14T04:24:25.531Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/c1/c4/67df9963395e9dddd4e16cbf75098953798e5135f73fb8f4855895505e39/djangorestframework_guardian-0.4.0.tar.gz", hash = "sha256:a8113659e062f65b74cc31af6982420c382642e782d38581b3fdc748a179756c", size = 8239, upload-time = "2025-07-01T07:22:10.809Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/9b/cc/35c1d8fb99172b2646f29e270e9ec443ffe09e0b63e61cd528d4fb4b8b07/djangorestframework_guardian-0.3.0-py2.py3-none-any.whl", hash = "sha256:3bd3dd6ea58e1bceca5048faf6f8b1a93bb5dcff30ba5eb91b9a0e190a48a0c7", size = 6931, upload-time = "2019-08-02T01:00:39.543Z" },
|
{ url = "https://files.pythonhosted.org/packages/59/81/3d62f7ff71f7c45ec6664ebf03a4c736bf77f49481604361d40f8f4471e4/djangorestframework_guardian-0.4.0-py3-none-any.whl", hash = "sha256:30c2a349318c1cd603d6953d50d58159f9a0c833f5f8f5a811407d5984a39e14", size = 6064, upload-time = "2025-07-01T07:22:09.661Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -928,14 +900,14 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "drf-spectacular-sidecar"
|
name = "drf-spectacular-sidecar"
|
||||||
version = "2025.4.1"
|
version = "2025.8.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "django", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/5d/b6/ce857d73b65b86a9034d0604b5dc1a002f7fa218e32c4dba479a197acd70/drf_spectacular_sidecar-2025.4.1.tar.gz", hash = "sha256:ea7dc4e674174616589d258b5c9676f3c451ec422e62b79e31234d39db53922d", size = 2402076, upload-time = "2025-04-01T11:23:30.627Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/a9/f7/0cb2f520723f1823ef7b6651d447927f61ba92d152a5d68132599b90624f/drf_spectacular_sidecar-2025.8.1.tar.gz", hash = "sha256:1944ae0eb5136cff5aa135211bec31084cef1af03a04de9b7f2f912b3c59c251", size = 2407787, upload-time = "2025-08-01T11:28:01.319Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/cf/c3/d2f31ef748f89d68121aa3d4a71f7dfd44ea54957b84602d70cda2491c43/drf_spectacular_sidecar-2025.4.1-py3-none-any.whl", hash = "sha256:343a24b0d03125fa76d07685072f55779c5c4124d90c10b14e315fdc143ad9b9", size = 2422415, upload-time = "2025-04-01T11:23:28.797Z" },
|
{ url = "https://files.pythonhosted.org/packages/1f/3b/0fcdc6eb294a11ed6e3ddc02fc29968bf403d3ce31645764eedfc91f87a6/drf_spectacular_sidecar-2025.8.1-py3-none-any.whl", hash = "sha256:c65a2a423000cc067395150b4dc28e7398a762d66ee101c4c38a4fb0d29a42a2", size = 2427849, upload-time = "2025-08-01T11:27:59.648Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1411,15 +1383,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/c7/fc/4e5a141c3f7c7bed550ac1f69e599e92b6be449dd4677ec09f325cad0955/inotifyrecursive-0.3.5-py3-none-any.whl", hash = "sha256:7e5f4a2e1dc2bef0efa3b5f6b339c41fb4599055a2b54909d020e9e932cc8d2f", size = 8009, upload-time = "2020-11-20T12:38:46.981Z" },
|
{ url = "https://files.pythonhosted.org/packages/c7/fc/4e5a141c3f7c7bed550ac1f69e599e92b6be449dd4677ec09f325cad0955/inotifyrecursive-0.3.5-py3-none-any.whl", hash = "sha256:7e5f4a2e1dc2bef0efa3b5f6b339c41fb4599055a2b54909d020e9e932cc8d2f", size = 8009, upload-time = "2020-11-20T12:38:46.981Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "isodate"
|
|
||||||
version = "0.7.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/54/4d/e940025e2ce31a8ce1202635910747e5a87cc3a6a6bb2d00973375014749/isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6", size = 29705 }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/15/aa/0aca39a37d3c7eb941ba736ede56d689e7be91cab5d9ca846bde3999eba6/isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", size = 22320 },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinja2"
|
name = "jinja2"
|
||||||
version = "3.1.6"
|
version = "3.1.6"
|
||||||
@@ -1948,7 +1911,6 @@ name = "paperless-ngx"
|
|||||||
version = "2.17.1"
|
version = "2.17.1"
|
||||||
source = { virtual = "." }
|
source = { virtual = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "azure-ai-documentintelligence", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
{ name = "bleach", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "bleach", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "celery", extra = ["redis"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "celery", extra = ["redis"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "channels", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "channels", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
@@ -2082,29 +2044,28 @@ typing = [
|
|||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "azure-ai-documentintelligence", specifier = ">=1.0.2" },
|
|
||||||
{ name = "bleach", specifier = "~=6.2.0" },
|
{ name = "bleach", specifier = "~=6.2.0" },
|
||||||
{ name = "celery", extras = ["redis"], specifier = "~=5.5.1" },
|
{ name = "celery", extras = ["redis"], specifier = "~=5.5.1" },
|
||||||
{ name = "channels", specifier = "~=4.2" },
|
{ name = "channels", specifier = "~=4.2" },
|
||||||
{ name = "channels-redis", specifier = "~=4.2" },
|
{ name = "channels-redis", specifier = "~=4.2" },
|
||||||
{ name = "concurrent-log-handler", specifier = "~=0.9.25" },
|
{ name = "concurrent-log-handler", specifier = "~=0.9.25" },
|
||||||
{ name = "dateparser", specifier = "~=1.2" },
|
{ name = "dateparser", specifier = "~=1.2" },
|
||||||
{ name = "django", specifier = "~=5.1.7" },
|
{ name = "django", specifier = "~=5.2.5" },
|
||||||
{ name = "django-allauth", extras = ["socialaccount", "mfa"], specifier = "~=65.4.0" },
|
{ name = "django-allauth", extras = ["socialaccount", "mfa"], specifier = "~=65.4.0" },
|
||||||
{ name = "django-auditlog", specifier = "~=3.1.2" },
|
{ name = "django-auditlog", specifier = "~=3.2.1" },
|
||||||
{ name = "django-cachalot", specifier = "~=2.8.0" },
|
{ name = "django-cachalot", specifier = "~=2.8.0" },
|
||||||
{ name = "django-celery-results", specifier = "~=2.6.0" },
|
{ name = "django-celery-results", specifier = "~=2.6.0" },
|
||||||
{ name = "django-compression-middleware", specifier = "~=0.5.0" },
|
{ name = "django-compression-middleware", specifier = "~=0.5.0" },
|
||||||
{ name = "django-cors-headers", specifier = "~=4.7.0" },
|
{ name = "django-cors-headers", specifier = "~=4.7.0" },
|
||||||
{ name = "django-extensions", specifier = "~=4.1" },
|
{ name = "django-extensions", specifier = "~=4.1" },
|
||||||
{ name = "django-filter", specifier = "~=25.1" },
|
{ name = "django-filter", specifier = "~=25.1" },
|
||||||
{ name = "django-guardian", specifier = "~=2.4.0" },
|
{ name = "django-guardian", specifier = "~=3.0.3" },
|
||||||
{ name = "django-multiselectfield", specifier = "~=0.1.13" },
|
{ name = "django-multiselectfield", specifier = "~=1.0.1" },
|
||||||
{ name = "django-soft-delete", specifier = "~=1.0.18" },
|
{ name = "django-soft-delete", specifier = "~=1.0.18" },
|
||||||
{ name = "djangorestframework", specifier = "~=3.15" },
|
{ name = "djangorestframework", specifier = "~=3.15" },
|
||||||
{ name = "djangorestframework-guardian", specifier = "~=0.3.0" },
|
{ name = "djangorestframework-guardian", specifier = "~=0.4.0" },
|
||||||
{ name = "drf-spectacular", specifier = "~=0.28" },
|
{ name = "drf-spectacular", specifier = "~=0.28" },
|
||||||
{ name = "drf-spectacular-sidecar", specifier = "~=2025.4.1" },
|
{ name = "drf-spectacular-sidecar", specifier = "~=2025.8.1" },
|
||||||
{ name = "drf-writable-nested", specifier = "~=0.7.1" },
|
{ name = "drf-writable-nested", specifier = "~=0.7.1" },
|
||||||
{ name = "filelock", specifier = "~=3.18.0" },
|
{ name = "filelock", specifier = "~=3.18.0" },
|
||||||
{ name = "flower", specifier = "~=2.0.1" },
|
{ name = "flower", specifier = "~=2.0.1" },
|
||||||
@@ -2158,7 +2119,7 @@ dev = [
|
|||||||
{ name = "pre-commit-uv", specifier = "~=4.1.3" },
|
{ name = "pre-commit-uv", specifier = "~=4.1.3" },
|
||||||
{ name = "pytest", specifier = "~=8.4.1" },
|
{ name = "pytest", specifier = "~=8.4.1" },
|
||||||
{ name = "pytest-cov", specifier = "~=6.2.1" },
|
{ name = "pytest-cov", specifier = "~=6.2.1" },
|
||||||
{ name = "pytest-django", specifier = "~=4.10.0" },
|
{ name = "pytest-django", specifier = "~=4.11.1" },
|
||||||
{ name = "pytest-env" },
|
{ name = "pytest-env" },
|
||||||
{ name = "pytest-httpx" },
|
{ name = "pytest-httpx" },
|
||||||
{ name = "pytest-mock" },
|
{ name = "pytest-mock" },
|
||||||
@@ -2182,7 +2143,7 @@ testing = [
|
|||||||
{ name = "imagehash" },
|
{ name = "imagehash" },
|
||||||
{ name = "pytest", specifier = "~=8.4.1" },
|
{ name = "pytest", specifier = "~=8.4.1" },
|
||||||
{ name = "pytest-cov", specifier = "~=6.2.1" },
|
{ name = "pytest-cov", specifier = "~=6.2.1" },
|
||||||
{ name = "pytest-django", specifier = "~=4.10.0" },
|
{ name = "pytest-django", specifier = "~=4.11.1" },
|
||||||
{ name = "pytest-env" },
|
{ name = "pytest-env" },
|
||||||
{ name = "pytest-httpx" },
|
{ name = "pytest-httpx" },
|
||||||
{ name = "pytest-mock" },
|
{ name = "pytest-mock" },
|
||||||
@@ -2636,14 +2597,14 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-django"
|
name = "pytest-django"
|
||||||
version = "4.10.0"
|
version = "4.11.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/a5/10/a096573b4b896f18a8390d9dafaffc054c1f613c60bf838300732e538890/pytest_django-4.10.0.tar.gz", hash = "sha256:1091b20ea1491fd04a310fc9aaff4c01b4e8450e3b157687625e16a6b5f3a366", size = 84710, upload-time = "2025-02-10T14:52:57.337Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/b1/fb/55d580352db26eb3d59ad50c64321ddfe228d3d8ac107db05387a2fadf3a/pytest_django-4.11.1.tar.gz", hash = "sha256:a949141a1ee103cb0e7a20f1451d355f83f5e4a5d07bdd4dcfdd1fd0ff227991", size = 86202, upload-time = "2025-04-03T18:56:09.338Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/58/4c/a4fe18205926216e1aebe1f125cba5bce444f91b6e4de4f49fa87e322775/pytest_django-4.10.0-py3-none-any.whl", hash = "sha256:57c74ef3aa9d89cae5a5d73fbb69a720a62673ade7ff13b9491872409a3f5918", size = 23975, upload-time = "2025-02-10T14:52:55.325Z" },
|
{ url = "https://files.pythonhosted.org/packages/be/ac/bd0608d229ec808e51a21044f3f2f27b9a37e7a0ebaca7247882e67876af/pytest_django-4.11.1-py3-none-any.whl", hash = "sha256:1b63773f648aa3d8541000c26929c1ea63934be1cfa674c76436966d73fe6a10", size = 25281, upload-time = "2025-04-03T18:56:07.678Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
Reference in New Issue
Block a user